diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index efff35eda7..440cde681b 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -4091,6 +4091,36 @@ describe('Plans Directory Initialization', () => { expect(context.getDirectories()).not.toContain(plansDir); }); + it('should gracefully fallback to default plans directory if retrieving custom directory throw an error', async () => { + vi.spyOn(coreEvents, 'emitFeedback'); + vi.spyOn(fs.promises, 'access').mockResolvedValue(undefined); + const config = new Config({ + ...baseParams, + plan: true, + planSettings: { + directory: '/outside/project/root', + }, + }); + + await config.initialize(); + + const plansDir = config.storage.getPlansDir(); + // Should fallback to default project temp plans dir + expect(plansDir).toContain('plans'); + expect(plansDir).not.toContain('/outside/project/root'); + + // Should emit a warning feedback + expect(coreEvents.emitFeedback).toHaveBeenCalledWith( + 'warning', + expect.stringContaining('Invalid custom plans directory'), + expect.any(Error), + ); + + // Should still add the fallback plans directory to workspace context if it exists + const context = config.getWorkspaceContext(); + expect(context.getDirectories()).toContain(plansDir); + }); + it('should NOT create plans directory or add it to workspace context when plan is disabled', async () => { const config = new Config({ ...baseParams, diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 985915e6ff..ec69d00518 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -1444,7 +1444,24 @@ export class Config implements McpContext, AgentLoopContext { // Add plans directory to workspace context for plan file storage if (this.planEnabled) { - const plansDir = this.storage.getPlansDir(); + let plansDir: string; + try { + plansDir = this.storage.getPlansDir(); + } catch (error) { + // Fallback to the default plan dir if any error occurs + const errorMessage = + error instanceof Error ? error.message : String(error); + coreEvents.emitFeedback( + 'warning', + 'Invalid custom plans directory: ' + + errorMessage + + '. Falling back to default project temp directory.', + error, + ); + this.storage.setCustomPlansDir(undefined); + plansDir = this.storage.getPlansDir(); + } + try { await fs.promises.access(plansDir); this.workspaceContext.addDirectory(plansDir);