Yeachan-Heo/oh-my-codex · warning

[omx] warning: failed to stop stale notify fallback watcher

Error message

[omx] warning: failed to stop stale notify fallback watcher

What it means

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.

Source

Thrown at src/cli/index.ts:7711

  const warn = deps.warn ?? console.warn;
  const isWatcherProcessImpl = deps.isWatcherProcess ?? isLikelyOmxWatcherProcess;

  try {
    const record = parseWatcherPidRecord(await readFileImpl(pidPath, "utf-8"));
    if (!record) return "invalid";
    if (!isWatcherProcessImpl(record.pid)) return "identity_mismatch";
    if (isWatcherRecordWithinReapGrace(
      record,
      deps.nowMs?.() ?? Date.now(),
      deps.reapGraceMs ?? resolveNotifyFallbackReapGraceMs(),
    )) {
      return "recent_active";
    }
    tryKillPidImpl(record.pid, "SIGTERM");
    return "reaped";
  } catch (error: unknown) {
    if (!hasErrnoCodeImpl(error, "ESRCH")) {
      warn(
        "[omx] warning: failed to stop stale notify fallback watcher",
        {
          path: pidPath,
          error: error instanceof Error ? error.message : String(error),
        },
      );
    }
    return "failed";
  }
}

function tryKillPid(pid: number, signal: NodeJS.Signals = "SIGTERM"): boolean {
  try {
    process.kill(pid, signal);
    return true;
  } catch (error: unknown) {
    const code = (error as NodeJS.ErrnoException).code;
    if (code === "ESRCH") return false;

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Delete the stale pid file under <cwd>/.omx/state/ (or the omx root state dir)
  2. Verify no watcher is actually running: `ps -p $(cat *.pid)`
  3. Run the CLI as the same user that created the watcher

Example fix

// before
rm -f .omx/state/notify-fallback-watcher.pid   # unknown stale pid

# after
kill $(cat .omx/state/notify-fallback-watcher.pid) 2>/dev/null; rm -f .omx/state/notify-fallback-watcher.pid
Defensive patterns

Strategy: try-catch

Validate before calling

import { existsSync, readFileSync } from 'node:fs';
function readablePidFile(p: string): boolean {
  try { return /^\d+\n?$/.test(readFileSync(p,'utf8')); } catch { return false; }
}

Try / catch

try { tryKillPidImpl(record.pid,'SIGTERM'); } catch (e) { if (!hasErrnoCodeImpl(e,'ESRCH')) warn(...); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/f067498300f187d1. Report an issue: GitHub.