{"record":{"id":"d47932083397cb4a","repo":"Yeachan-Heo/oh-my-codex","slug":"notify-hook-exited-result-status-result-std","errorCode":null,"errorMessage":"notify-hook exited ${result.status}: ${(result.stderr || result.stdout || '').trim()}","messagePattern":"notify-hook exited (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/tmux-hook.ts","lineNumber":477,"sourceCode":"  const payload = {\n    type: 'agent-turn-complete',\n    cwd,\n    'thread-id': threadId,\n    'turn-id': turnId,\n    'input-messages': ['omx tmux-hook test'],\n    'last-assistant-message': message,\n  };\n\n  const result = spawnSync(process.execPath, [notifyHook, JSON.stringify(payload)], {\n    cwd,\n    encoding: 'utf-8',\n      windowsHide: true,\n    });\n  if (result.error) {\n    throw new Error(`failed to run notify-hook: ${result.error.message}`);\n  }\n  if (result.status !== 0) {\n    throw new Error(`notify-hook exited ${result.status}: ${(result.stderr || result.stdout || '').trim()}`);\n  }\n\n  console.log('tmux-hook test: notify-hook executed.');\n  console.log(`thread_id=${threadId}`);\n  console.log(`turn_id=${turnId}`);\n  console.log('Check: .omx/logs/tmux-hook-YYYY-MM-DD.jsonl for skip/reason codes.');\n}\n","sourceCodeStart":459,"sourceCodeEnd":485,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/tmux-hook.ts#L459-L485","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nomx tmux-hook test hello\n# Error: notify-hook exited 1: skip reason=invalid_config target=placeholder\n\n# after\nomx tmux-hook init --target mysession:0.0\nomx tmux-hook test hello","handlingStrategy":"try-catch","validationCode":"null","typeGuard":null,"tryCatchPattern":"try { await testTmuxHook(args); } catch (e) {\n  if (e instanceof Error && e.message.startsWith('notify-hook exited')) {\n    const reason = e.message.split(':').pop()?.trim();\n    if (reason.includes('invalid_config')) await reinitAgainstRealTmuxTarget();\n    else console.error('inspect .omx/logs/tmux-hook-*.jsonl for skip codes');\n  } else throw e;\n}","preventionTips":["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"],"tags":["cli","tmux","hook","non-zero-exit","diagnostics"],"backgroundTag":"hook-script-non-zero-exit","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}