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

failed to kill tmux pane ${finalProof.paneId}: ${result.stde

Error message

failed to kill tmux pane ${finalProof.paneId}: ${result.stderr}

What it means

The `tmux kill-pane -t <paneId>` command itself returned non-zero after all identity proofs passed. The pane could not be killed at the tmux level; stderr is embedded. This leaves the pane live and cleanup incomplete.

Source

Thrown at src/team/tmux-session.ts:609

function killExactPaneSync(paneId: string, expectedPid?: number, assertAuthorization?: () => void): void {
  const proof = readExactPaneProofSync(paneId);
  if (proof.status === 'unavailable') throw new ExactPaneProofUnavailableError(proof);
  if (proof.status === 'gone') return;
  if (expectedPid !== undefined && proof.pid !== expectedPid) {
    throw new Error(`tmux pane identity changed: ${paneId}`);
  }
  assertAuthorization?.();
  // Authorization can read tmux. Re-prove immediately after it so a recycled
  // pane ID cannot be targeted by the subsequent kill.
  const finalProof = readExactPaneProofSync(proof.paneId);
  if (finalProof.status === 'unavailable') throw new ExactPaneProofUnavailableError(finalProof);
  if (finalProof.status === 'gone') return;
  if (finalProof.pid !== proof.pid || (expectedPid !== undefined && finalProof.pid !== expectedPid)) {
    throw new Error(`tmux pane identity changed: ${paneId}`);
  }
  const result = runTmux(['kill-pane', '-t', finalProof.paneId]);
  if (!result.ok) throw new Error(`failed to kill tmux pane ${finalProof.paneId}: ${result.stderr}`);
  const afterKill = readExactPaneProofSync(finalProof.paneId);
  if (afterKill.status === 'unavailable') throw new ExactPaneProofUnavailableError(afterKill);
  if (afterKill.status !== 'gone') {
    if (afterKill.pid !== finalProof.pid) throw new Error(`tmux pane identity changed: ${paneId}`);
    throw new Error(`tmux pane remains live after kill: ${paneId}`);
  }
}

function appendNoUnderlineStyleFlags(style: string): string {
  const normalized = style
    .split(/[,\s]+/)
    .map((token) => token.trim())
    .filter((token) => token.length > 0);
  const combined = [...normalized];
  for (const flag of TMUX_NO_UNDERLINE_STYLE_FLAGS) {
    if (!combined.includes(flag)) combined.push(flag);
  }
  return combined.join(',');

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Read embedded stderr; 'no such pane' usually means it is already gone — verify with a proof and treat as done
  2. If it is the session's last pane, kill the session/window instead
  3. Retry once after re-proving identity
Defensive patterns

Strategy: retry

Try / catch

catch (e) { if (/failed to kill tmux pane/.test(e.message)) { const p = readExactPaneProofSync(paneId); if (p.status === 'gone') return; retryOnce(); return; } throw e; }

Prevention

When it happens

Trigger: killExactPaneSync when the tmux server errors on kill-pane: pane is the last pane of a session needing kill-session, server-side internal error, or the pane vanished with a race that reported failure.

Common situations: Killing the last pane of a window/session where tmux refuses or cascades oddly; very old tmux bugs; permission/socket issues.

Related errors


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