Skip to content

Commit 7a6dd96

Browse files
author
Giancarlo Erra
committed
fix(startup): keep incremental catch-up alive when watcher startup throws
startWatching can throw outside its internal guard (lock-file writes, gitignore reads). Wrap it so a watcher failure degrades to a warning instead of skipping the project's catch-up update, which would leave the index stale.
1 parent a7f639f commit 7a6dd96

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

src/services/startup.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,21 @@ async function resumeProject(
267267
return;
268268
}
269269

270-
// Index is complete — start watcher and do incremental catch-up
270+
// Index is complete — start watcher and do incremental catch-up.
271+
// Watcher startup failure must not skip the catch-up below: a project
272+
// without a live watcher is degraded, but a project with a stale index
273+
// is broken for search.
271274
if (!isWatching(resolvedPath)) {
272-
const started = await startWatching(resolvedPath);
273-
if (started) {
274-
logger.info("Auto-resume: started file watcher", { projectPath: resolvedPath });
275+
try {
276+
const started = await startWatching(resolvedPath);
277+
if (started) {
278+
logger.info("Auto-resume: started file watcher", { projectPath: resolvedPath });
279+
}
280+
} catch (err) {
281+
logger.warn("Auto-resume: failed to start watcher, continuing with incremental catch-up", {
282+
projectPath: resolvedPath,
283+
error: err instanceof Error ? err.message : String(err),
284+
});
275285
}
276286
}
277287

tests/unit/startup.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,21 @@ describe("autoResumeIndexedProjects (multi-project modes)", () => {
554554
expect(mockUpdateProjectIndex).not.toHaveBeenCalled();
555555
});
556556

557+
it("still runs the incremental catch-up when watcher startup throws", async () => {
558+
process.env.SOCRATICODE_AUTO_RESUME_PROJECTS = dirA;
559+
mockStartWatching.mockRejectedValue(new Error("inotify limit reached"));
560+
561+
await autoResumeIndexedProjects();
562+
563+
// A project without a live watcher is degraded; a project with a stale
564+
// index is broken for search. The catch-up must survive watcher failure.
565+
expect(logger.warn).toHaveBeenCalledWith(
566+
"Auto-resume: failed to start watcher, continuing with incremental catch-up",
567+
expect.objectContaining({ projectPath: dirA, error: "inotify limit reached" }),
568+
);
569+
expect(mockUpdateProjectIndex).toHaveBeenCalledWith(dirA);
570+
});
571+
557572
it("unrecognized SOCRATICODE_AUTO_RESUME value warns and falls back to default cwd behavior", async () => {
558573
process.env.SOCRATICODE_AUTO_RESUME = "yes";
559574
mockListCollections.mockResolvedValue([collA]);

0 commit comments

Comments
 (0)