Yeachan-Heo/oh-my-codex · error · Error

notify-hook exited ${result.status}: ${(result.stderr || res

Error message

notify-hook exited ${result.status}: ${(result.stderr || result.stdout || '').trim()}

What it means

The tmux-hook test subcommand executed notify-hook.js but the hook process exited with a non-zero status. The message embeds the hook's trimmed stderr (or stdout) so the underlying cause — usually an invalid_config skip logged by the hook itself — surfaces directly.

Source

Thrown at src/cli/tmux-hook.ts:477

  const payload = {
    type: 'agent-turn-complete',
    cwd,
    'thread-id': threadId,
    'turn-id': turnId,
    'input-messages': ['omx tmux-hook test'],
    'last-assistant-message': message,
  };

  const result = spawnSync(process.execPath, [notifyHook, JSON.stringify(payload)], {
    cwd,
    encoding: 'utf-8',
      windowsHide: true,
    });
  if (result.error) {
    throw new Error(`failed to run notify-hook: ${result.error.message}`);
  }
  if (result.status !== 0) {
    throw new Error(`notify-hook exited ${result.status}: ${(result.stderr || result.stdout || '').trim()}`);
  }

  console.log('tmux-hook test: notify-hook executed.');
  console.log(`thread_id=${threadId}`);
  console.log(`turn_id=${turnId}`);
  console.log('Check: .omx/logs/tmux-hook-YYYY-MM-DD.jsonl for skip/reason codes.');
}

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Read the embedded stderr/stdout in the message — it names the skip reason (e.g. invalid_config)
  2. Run `omx tmux-hook init` against a real tmux target (not the placeholder), then re-test
  3. Check .omx/logs/tmux-hook-YYYY-MM-DD.jsonl for the skip/reason code as the console output suggests
  4. Verify config.enabled and allowed_modes allow the test payload

Example fix

# before
omx tmux-hook test hello
# Error: notify-hook exited 1: skip reason=invalid_config target=placeholder

# after
omx tmux-hook init --target mysession:0.0
omx tmux-hook test hello
Defensive patterns

Strategy: try-catch

Validate before calling

null

Try / catch

try { await testTmuxHook(args); } catch (e) {
  if (e instanceof Error && e.message.startsWith('notify-hook exited')) {
    const reason = e.message.split(':').pop()?.trim();
    if (reason.includes('invalid_config')) await reinitAgainstRealTmuxTarget();
    else console.error('inspect .omx/logs/tmux-hook-*.jsonl for skip codes');
  } else throw e;
}

Prevention

When it happens

Trigger: notify-hook.js receives a JSON payload it considers invalid: missing/placeholder tmux target config (the code above warns 'notify-hook may log invalid_config skips' when a placeholder target was used), disabled mode gating, malformed payload fields, or an internal hook exception writing to stderr.

Common situations: Running the test against a placeholder target from init instead of a real tmux pane; config.enabled=false or allowed_modes gating rejects the payload; hook version drift where payload schema changed.

Related errors


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