{"record":{"id":"c49f9199dfc01281","repo":"Yeachan-Heo/oh-my-codex","slug":"unavailable","errorCode":null,"errorMessage":"unavailable","messagePattern":"unavailable","errorType":"exception","errorClass":"ExactPaneProofUnavailableError","httpStatus":null,"severity":"error","filePath":"src/team/tmux-session.ts","lineNumber":584,"sourceCode":"  const topology = listPanesResult(leader);\n  const hudMatches = !topology.error && topology.panes.filter((pane) => pane.paneId === debt.pane_id\n    && hudPaneMatchesOwner(pane, { leaderPaneId: debt.hud_owner_leader_pane_id })).length === 1;\n  if (!hudMatches) throw new Error(`restored_hud_cleanup_debt_unresolved:${debt.pane_id}`);\n  const finalProof = readExactPaneProofSync(debt.pane_id);\n  if (finalProof.status !== 'live' || finalProof.pid !== debt.pane_pid) {\n    throw new Error(`restored_hud_cleanup_debt_unresolved:${debt.pane_id}`);\n  }\n  removeRestoredHudCleanupDebtSync(record.path);\n}\n\n\n/**\n * Kill only a pane that a fresh global snapshot proves live. Callers treat\n * gone/dead rows as already cleaned and unavailable snapshots as fail-closed.\n */\nfunction requireLiveExactPaneSync(paneId: string, expectedPid?: number): string {\n  const proof = readExactPaneProofSync(paneId);\n  if (proof.status === 'unavailable') throw new ExactPaneProofUnavailableError(proof);\n  if (proof.status === 'gone') throw new Error(`tmux pane is not proven live: ${paneId}`);\n  if (expectedPid !== undefined && proof.pid !== expectedPid) {\n    throw new Error(`tmux pane identity changed: ${paneId}`);\n  }\n  return proof.paneId;\n}\n\nfunction killExactPaneSync(paneId: string, expectedPid?: number, assertAuthorization?: () => void): void {\n  const proof = readExactPaneProofSync(paneId);\n  if (proof.status === 'unavailable') throw new ExactPaneProofUnavailableError(proof);\n  if (proof.status === 'gone') return;\n  if (expectedPid !== undefined && proof.pid !== expectedPid) {\n    throw new Error(`tmux pane identity changed: ${paneId}`);\n  }\n  assertAuthorization?.();\n  // Authorization can read tmux. Re-prove immediately after it so a recycled\n  // pane ID cannot be targeted by the subsequent kill.\n  const finalProof = readExactPaneProofSync(proof.paneId);","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/team/tmux-session.ts#L566-L602","documentation":"ExactPaneProofUnavailableError thrown from requireLiveExactPaneSync: the global pane snapshot (readExactPaneProofSync) could not decide liveness — status 'unavailable' (full message: exact_pane_proof_unavailable:<paneId>:<reason>). The library fails closed: without proof, it neither acts nor assumes the pane is gone.","triggerScenarios":"tmux list-panes global snapshot fails or times out: server not running, socket unreachable, tmux binary missing, or spawn error. Any requireLiveExactPaneSync call can raise it.","commonSituations":"tmux server died; TMUX_TMPDIR/TMUX env mismatch so the client talks to the wrong socket; tmux not installed on PATH; resource exhaustion preventing process spawn.","solutions":["Check proof.reason in the error object: 'no server' means nothing is running (treat panes as gone if appropriate for your flow)","Fix environment: consistent TMUX/TMUX_TMPDIR, tmux on PATH","Retry after the tmux server is back; surface unavailability distinctly from identity failures"],"exampleFix":"// before\nrequireLiveExactPaneSync(paneId);\n// after\ntry { requireLiveExactPaneSync(paneId); }\ncatch (e) {\n  if (e.message.startsWith('exact_pane_proof_unavailable:')) { /* fail-closed: reschedule */ }\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"if (!runTmuxStructured(['list-sessions']).ok) throw new Error('tmux server unreachable; deferring pane ops');","typeGuard":"function isProofUnavailable(e: unknown): boolean { return e instanceof Error && e.message.startsWith('exact_pane_proof_unavailable:'); }","tryCatchPattern":"catch (e) { if (isProofUnavailable(e)) { deferAndRetry(); return; } throw e; }","preventionTips":["Distinguish unavailability (transient, retry) from identity change (permanent)","Keep tmux on PATH and TMUX socket env consistent"],"tags":["tmux","fail-closed","liveness"],"backgroundTag":"tmux-server-unreachable","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}