fix: narrow watcher transient classifier

This commit is contained in:
Altay
2026-05-02 19:24:43 +03:00
parent b6c8058d46
commit 494ca27b8b
2 changed files with 20 additions and 6 deletions

View File

@@ -308,9 +308,18 @@ describe("isTransientFileWatchError", () => {
).toBe(true);
});
it("returns true for watcher-related error messages", () => {
it("returns true for watcher-related ENOSPC messages", () => {
expect(isTransientFileWatchError(new Error("watcher error: ENOSPC"))).toBe(true);
expect(isTransientFileWatchError(new Error("file watcher failed"))).toBe(true);
expect(isTransientFileWatchError(new Error("file watcher: no space left on device"))).toBe(
true,
);
});
it("returns false for generic code-less watcher messages", () => {
expect(isTransientFileWatchError(new Error("file watcher failed"))).toBe(false);
expect(isTransientFileWatchError(new Error("watcher error: boom"))).toBe(false);
expect(isTransientUnhandledRejectionError(new Error("file watcher failed"))).toBe(false);
expect(isTransientUnhandledRejectionError(new Error("watcher error: boom"))).toBe(false);
});
it("returns true for ENOSPC with cause chain containing watch indicator", () => {

View File

@@ -371,6 +371,12 @@ export function isTransientFileWatchError(err: unknown): boolean {
message.includes("file watcher") ||
message.includes("watch limit") ||
message.includes("max watches");
const hasFileWatchExhaustionSignal = (message: string) =>
message.includes("inotify watches") ||
message.includes("inotify watch") ||
message.includes("system limit for number of file watchers") ||
message.includes("watch limit") ||
message.includes("max watches");
for (const candidate of collectNestedUnhandledErrorCandidates(err)) {
// Skip non-object candidates early
@@ -393,16 +399,15 @@ export function isTransientFileWatchError(err: unknown): boolean {
continue;
}
// Check for file watcher error message patterns (without ENOSPC code)
// Without an ENOSPC code, only classify explicit watcher resource exhaustion.
// Generic "file watcher failed" labels can wrap permission/config/runtime failures.
if (!message) {
continue;
}
if (
((message.includes("no space left on device") || message.includes("enosp")) &&
hasFileWatchSignal(message)) ||
message.includes("inotify watches") ||
message.includes("file watcher") ||
message.includes("watcher error")
hasFileWatchExhaustionSignal(message)
) {
return true;
}