Yeachan-Heo/oh-my-codex · warning

[omx] warning: failed to remove notify fallback watcher pid

Error message

[omx] warning: failed to remove notify fallback watcher pid file

What it means

After stopping the watcher, unlink(pidPath) failed to remove the PID file (error swallowed). A stale pid file remains and the next run may try to kill a reused PID.

Source

Thrown at src/cli/index.ts:7913

  try {
    const pid = parseWatcherPidFile(await readFile(pidPath, "utf-8"));
    if (pid) {
      tryKillPid(pid, "SIGTERM");
    }
  } catch (error: unknown) {
    if (!hasErrnoCode(error, "ESRCH")) {
      console.warn(
        "[omx] warning: failed to stop notify fallback watcher process",
        {
          path: pidPath,
          error: error instanceof Error ? error.message : String(error),
        },
      );
    }
  }

  await unlink(pidPath).catch((error: unknown) => {
    console.warn(
      "[omx] warning: failed to remove notify fallback watcher pid file",
      {
        path: pidPath,
        error: error instanceof Error ? error.message : String(error),
      },
    );
  });
}

async function stopHookDerivedWatcher(cwd: string): Promise<void> {
  const { readFile, unlink } = await import("fs/promises");
  const pidPath = hookDerivedWatcherPidPath(cwd);
  if (!existsSync(pidPath)) return;

  try {
    const parsed = JSON.parse(await readFile(pidPath, "utf-8")) as {
      pid?: number;
    };

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Manually remove the pid file
  2. chown/chmod the state directory for the current user
  3. Avoid mixing sudo and non-sudo omx runs

Example fix

// before
rm .omx/state/notify-fallback-watcher.pid   # permission denied

# after
sudo chown -R $USER .omx && rm .omx/state/notify-fallback-watcher.pid
Defensive patterns

Strategy: validation

Validate before calling

import { accessSync, constants, dirname } from 'node:fs';
function pathRemovable(p: string): boolean {
  try { accessSync(dirname(p), constants.W_OK); return true; } catch { return false; }
}

Try / catch

await unlink(pidPath).catch((e: unknown) => { if ((e as NodeJS.ErrnoException).code !== 'ENOENT') console.warn(...); });

Prevention

When it happens

Trigger: unlink rejects with EACCES/EPERM/EROFS — file owned by another user, directory not writable, or read-only filesystem.

Common situations: State files created under root/sudo then used as normal user; read-only mounts; restrictive ACLs.

Related errors


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