Yeachan-Heo/oh-my-codex · warning

[omx] warning: failed to write hook-derived watcher pid file

Error message

[omx] warning: failed to write hook-derived watcher pid file

What it means

The hook-derived watcher started but its PID file could not be written (writeFile rejected, caught). Future runs cannot locate/stop this watcher cleanly.

Source

Thrown at src/cli/index.ts:7880

  } catch (error: unknown) {
    console.warn("[omx] warning: failed to launch hook-derived watcher", {
      cwd,
      error: error instanceof Error ? error.message : String(error),
    });
    return;
  }

  if (!watcherPid) return;

  await writeFile(
    pidPath,
    JSON.stringify(
      { pid: watcherPid, started_at: new Date().toISOString() },
      null,
      2,
    ),
  ).catch((error: unknown) => {
    console.warn(
      "[omx] warning: failed to write hook-derived watcher pid file",
      {
        path: pidPath,
        error: error instanceof Error ? error.message : String(error),
      },
    );
  });
}

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

  try {
    const pid = parseWatcherPidFile(await readFile(pidPath, "utf-8"));
    if (pid) {
      tryKillPid(pid, "SIGTERM");

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Free disk space and re-run
  2. Pre-create and verify writability: `touch .omx/state/.write-test`
  3. Avoid running concurrent setup/teardown commands on the same project

Example fix

// before
touch .omx/state/t  # permission denied

# after
chown -R $USER .omx && touch .omx/state/t && rm .omx/state/t
Defensive patterns

Strategy: validation

Validate before calling

import { accessSync, constants, existsSync, statSync } from 'node:fs';
function pidFileWritable(path: string): boolean {
  if (existsSync(path)) { try { accessSync(path, constants.W_OK); return statSync(path).isFile(); } catch { return false; } }
  try { accessSync(require('node:path').dirname(path), constants.W_OK); return true; } catch { return false; }
}

Prevention

When it happens

Trigger: writeFile of {pid, started_at} JSON to state rejects: ENOSPC, EACCES, or the state dir was deleted between mkdir and write.

Common situations: Full disks in CI; concurrent cleanup; permission changes mid-run.

Related errors


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