Skip to content

Commit 2745c9a

Browse files
committed
fix: improve error handling and validation in code indexing process
1 parent 3725ebd commit 2745c9a

File tree

3 files changed

+62
-24
lines changed

3 files changed

+62
-24
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,9 +1869,6 @@ export const webviewMessageHandler = async (
18691869
)
18701870
}
18711871

1872-
// Verify secrets are actually stored
1873-
const storedOpenAiKey = provider.contextProxy.getSecret("codeIndexOpenAiKey")
1874-
18751872
// Send success response first - settings are saved regardless of validation
18761873
await provider.postMessageToWebview({
18771874
type: "codeIndexSettingsSaved",
@@ -1904,35 +1901,35 @@ export const webviewMessageHandler = async (
19041901
}
19051902
} else {
19061903
// No provider change, just handle settings normally
1907-
await provider.codeIndexManager.handleSettingsChange()
1904+
try {
1905+
await provider.codeIndexManager.handleSettingsChange()
1906+
} catch (error) {
1907+
// Log but don't fail - settings are saved
1908+
provider.log(
1909+
`Settings change handling error: ${error instanceof Error ? error.message : String(error)}`,
1910+
)
1911+
}
19081912
}
19091913

1914+
// Wait a bit more to ensure everything is ready
1915+
await new Promise((resolve) => setTimeout(resolve, 200))
1916+
19101917
// Auto-start indexing if now enabled and configured
19111918
if (provider.codeIndexManager.isFeatureEnabled && provider.codeIndexManager.isFeatureConfigured) {
19121919
if (!provider.codeIndexManager.isInitialized) {
19131920
try {
1914-
// Initialize will validate embedder configuration
1915-
const { requiresRestart } = await provider.codeIndexManager.initialize(
1916-
provider.contextProxy,
1917-
)
1918-
1919-
// If initialization succeeded (no exception thrown), start indexing
1920-
provider.codeIndexManager.startIndexing()
1921+
await provider.codeIndexManager.initialize(provider.contextProxy)
1922+
provider.log(`Code index manager initialized after settings save`)
19211923
} catch (error) {
1922-
// Log the specific validation error for debugging
19231924
provider.log(
1924-
`Code index initialization failed during settings save: ${error instanceof Error ? error.message : String(error)}`,
1925+
`Code index initialization failed: ${error instanceof Error ? error.message : String(error)}`,
19251926
)
19261927
// Send error status to webview
19271928
await provider.postMessageToWebview({
19281929
type: "indexingStatusUpdate",
19291930
values: provider.codeIndexManager.getCurrentStatus(),
19301931
})
1931-
// Don't re-throw - settings are already saved successfully
19321932
}
1933-
} else {
1934-
// Already initialized, just start indexing
1935-
provider.codeIndexManager.startIndexing()
19361933
}
19371934
}
19381935
}

src/services/code-index/manager.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,14 @@ export class CodeIndexManager {
118118
return { requiresRestart }
119119
}
120120

121-
// 3. CacheManager Initialization
121+
// 3. Check if workspace is available
122+
const workspacePath = getWorkspacePath()
123+
if (!workspacePath) {
124+
this._stateManager.setSystemState("Standby", "No workspace folder open")
125+
return { requiresRestart }
126+
}
127+
128+
// 4. CacheManager Initialization
122129
if (!this._cacheManager) {
123130
this._cacheManager = new CacheManager(this.context, this.workspacePath)
124131
await this._cacheManager.initialize()
@@ -215,6 +222,9 @@ export class CodeIndexManager {
215222
if (this._orchestrator) {
216223
this.stopWatcher()
217224
}
225+
// Clear existing services to ensure clean state
226+
this._orchestrator = undefined
227+
this._searchService = undefined
218228

219229
// (Re)Initialize service factory
220230
this._serviceFactory = new CodeIndexServiceFactory(
@@ -224,7 +234,14 @@ export class CodeIndexManager {
224234
)
225235

226236
const ignoreInstance = ignore()
227-
const ignorePath = path.join(getWorkspacePath(), ".gitignore")
237+
const workspacePath = getWorkspacePath()
238+
239+
if (!workspacePath) {
240+
this._stateManager.setSystemState("Standby", "")
241+
return
242+
}
243+
244+
const ignorePath = path.join(workspacePath, ".gitignore")
228245
try {
229246
const content = await fs.readFile(ignorePath, "utf8")
230247
ignoreInstance.add(content)
@@ -270,6 +287,9 @@ export class CodeIndexManager {
270287
embedder,
271288
vectorStore,
272289
)
290+
291+
// Clear any error state after successful recreation
292+
this._stateManager.setSystemState("Standby", "")
273293
}
274294

275295
/**
@@ -285,14 +305,10 @@ export class CodeIndexManager {
285305
const isFeatureEnabled = this.isFeatureEnabled
286306
const isFeatureConfigured = this.isFeatureConfigured
287307

288-
// If configuration changes require a restart and the manager is initialized, restart the service
289-
if (requiresRestart && isFeatureEnabled && isFeatureConfigured && this.isInitialized) {
308+
if (requiresRestart && isFeatureEnabled && isFeatureConfigured) {
290309
try {
291310
// Recreate services with new configuration
292311
await this._recreateServices()
293-
294-
// Start indexing with new services
295-
this.startIndexing()
296312
} catch (error) {
297313
// Error state already set in _recreateServices
298314
console.error("Failed to recreate services:", error)

src/services/code-index/orchestrator.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,31 @@ export class CodeIndexOrchestrator {
164164
}
165165
}
166166

167+
// Check for partial failures - if a significant portion of blocks failed
168+
const failureRate = (cumulativeBlocksFoundSoFar - cumulativeBlocksIndexed) / cumulativeBlocksFoundSoFar
169+
if (batchErrors.length > 0 && failureRate > 0.1) {
170+
// More than 10% of blocks failed to index
171+
const firstError = batchErrors[0]
172+
throw new Error(
173+
`Indexing partially failed: Only ${cumulativeBlocksIndexed} of ${cumulativeBlocksFoundSoFar} blocks were indexed. ${firstError.message}`,
174+
)
175+
}
176+
177+
// CRITICAL: If there were ANY batch errors and NO blocks were successfully indexed,
178+
// this is a complete failure regardless of the failure rate calculation
179+
if (batchErrors.length > 0 && cumulativeBlocksIndexed === 0) {
180+
const firstError = batchErrors[0]
181+
throw new Error(`Indexing failed completely: ${firstError.message}`)
182+
}
183+
184+
// Final sanity check: If we found blocks but indexed none and somehow no errors were reported,
185+
// this is still a failure
186+
if (cumulativeBlocksFoundSoFar > 0 && cumulativeBlocksIndexed === 0) {
187+
throw new Error(
188+
"Indexing failed: No code blocks were successfully indexed despite finding files to process. This indicates a critical embedder failure.",
189+
)
190+
}
191+
167192
await this._startWatcher()
168193

169194
this.stateManager.setSystemState("Indexed", "File watcher started.")

0 commit comments

Comments
 (0)