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
- Read the embedded stderr/stdout in the message — it names the skip reason (e.g. invalid_config)
- Run `omx tmux-hook init` against a real tmux target (not the placeholder), then re-test
- Check .omx/logs/tmux-hook-YYYY-MM-DD.jsonl for the skip/reason code as the console output suggests
- 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
- Always init against a real tmux target before running test
- Check .omx/logs/tmux-hook-YYYY-MM-DD.jsonl after failures
- Ensure config.enabled and allowed_modes admit the test payload
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
- --tmux-pane requires a pane id. ${SPARKSHELL_USAGE}
- --tail-lines requires a numeric value. ${SPARKSHELL_USAGE}
- --tail-lines must be an integer between 100 and 1000. ${SPAR
- tmux pane mode does not accept an additional command. ${SPAR
- Unknown tmux-hook subcommand: ${subcommand}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/d47932083397cb4a.
Report an issue: GitHub.