{"record":{"id":"f067498300f187d1","repo":"Yeachan-Heo/oh-my-codex","slug":"omx-warning-failed-to-stop-stale-notify-fallbac","errorCode":null,"errorMessage":"[omx] warning: failed to stop stale notify fallback watcher","messagePattern":"\\[omx\\] warning: failed to stop stale notify fallback watcher","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/cli/index.ts","lineNumber":7711,"sourceCode":"  const warn = deps.warn ?? console.warn;\n  const isWatcherProcessImpl = deps.isWatcherProcess ?? isLikelyOmxWatcherProcess;\n\n  try {\n    const record = parseWatcherPidRecord(await readFileImpl(pidPath, \"utf-8\"));\n    if (!record) return \"invalid\";\n    if (!isWatcherProcessImpl(record.pid)) return \"identity_mismatch\";\n    if (isWatcherRecordWithinReapGrace(\n      record,\n      deps.nowMs?.() ?? Date.now(),\n      deps.reapGraceMs ?? resolveNotifyFallbackReapGraceMs(),\n    )) {\n      return \"recent_active\";\n    }\n    tryKillPidImpl(record.pid, \"SIGTERM\");\n    return \"reaped\";\n  } catch (error: unknown) {\n    if (!hasErrnoCodeImpl(error, \"ESRCH\")) {\n      warn(\n        \"[omx] warning: failed to stop stale notify fallback watcher\",\n        {\n          path: pidPath,\n          error: error instanceof Error ? error.message : String(error),\n        },\n      );\n    }\n    return \"failed\";\n  }\n}\n\nfunction tryKillPid(pid: number, signal: NodeJS.Signals = \"SIGTERM\"): boolean {\n  try {\n    process.kill(pid, signal);\n    return true;\n  } catch (error: unknown) {\n    const code = (error as NodeJS.ErrnoException).code;\n    if (code === \"ESRCH\") return false;","sourceCodeStart":7693,"sourceCodeEnd":7729,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/index.ts#L7693-L7729","documentation":"While reaping a stale notify fallback watcher, the CLI read a PID file and tried to SIGTERM the recorded PID, but the kill/parse path threw an error other than ESRCH (which would mean the process is already gone). Common causes: EPERM (PID owned by another user) or a corrupt PID file.","triggerScenarios":"Calling the stop-stale-watcher path when state/notify-fallback-watcher.pid contains a PID that cannot be signalled (EPERM) or a malformed value, and the thrown error lacks errno ESRCH.","commonSituations":"State directory shared between users or after user switching; PID reuse where the PID now belongs to a system process; truncated PID file after a crash.","solutions":["Delete the stale pid file under <cwd>/.omx/state/ (or the omx root state dir)","Verify no watcher is actually running: `ps -p $(cat *.pid)`","Run the CLI as the same user that created the watcher"],"exampleFix":"// before\nrm -f .omx/state/notify-fallback-watcher.pid   # unknown stale pid\n\n# after\nkill $(cat .omx/state/notify-fallback-watcher.pid) 2>/dev/null; rm -f .omx/state/notify-fallback-watcher.pid","handlingStrategy":"try-catch","validationCode":"import { existsSync, readFileSync } from 'node:fs';\nfunction readablePidFile(p: string): boolean {\n  try { return /^\\d+\\n?$/.test(readFileSync(p,'utf8')); } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try { tryKillPidImpl(record.pid,'SIGTERM'); } catch (e) { if (!hasErrnoCodeImpl(e,'ESRCH')) warn(...); }","preventionTips":["Validate pid file contents before signalling","Run as the owning user of the state dir","Treat ESRCH as success (process already gone)"],"tags":["stale-pid-file","watcher","signal","eperm"],"backgroundTag":"stale-pid-file","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}