From cf6a494df463eefb8dece18e5710ed8d7e25c22e Mon Sep 17 00:00:00 2001 From: shixj Date: Thu, 4 Jun 2026 15:22:18 +0800 Subject: [PATCH] fix: guard initConfig against silent config reset on empty file load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When global or project config files are transiently inaccessible (I/O contention, race condition, missing files), loadConfigFromPaths() returns {}. Calling buildConfig({}) fills all fields with hardcoded defaults, then Object.assign(CONFIG, ...) overwrites the correctly initialized CONFIG singleton — silently breaking user-configured embedding model, dimensions, and API endpoint. The Web UI migration detection (/api/migration/detect) reads CONFIG.embeddingDimensions and CONFIG.embeddingModel to compare against shard metadata, so the reset manifests as a false dimension mismatch warning. Fix: skip CONFIG rebuild entirely when both config sources are empty. Closes #35 --- src/config.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/config.ts b/src/config.ts index 7968228..c72955f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -617,6 +617,17 @@ export function initConfig(directory: string): void { ]; const globalConfig = loadConfigFromPaths(CONFIG_FILES); const projectConfig = loadConfigFromPaths(projectPaths); + + // Guard: if neither global nor project config files were found (transient I/O + // failure, race condition, or missing files), do NOT rebuild the entire CONFIG + // from scratch. Calling buildConfig({}) with an empty object fills every field + // with hardcoded defaults — silently overwriting user-configured embedding + // dimensions, model, and API endpoint. The CONFIG singleton already carries + // the correct values from module-level initialization (line 593). + if (Object.keys(globalConfig).length === 0 && Object.keys(projectConfig).length === 0) { + return; + } + const merged = deepMerge(globalConfig, projectConfig); Object.assign(CONFIG, buildConfig(merged)); }