Yeachan-Heo/oh-my-codex · error · Error
failed to capture tmux source authority: ${result.stderr}
Error message
failed to capture tmux source authority: ${result.stderr} What it means
Thrown when `tmux display-message -p` fails while capturing the 'source pane authority' (session/window/pane identity tuple) for a pane that will authorize later tmux effects. The library refuses to proceed without a verified, fresh identity snapshot so it can never act on a recycled pane ID. The stderr of the underlying tmux command is embedded.
Source
Thrown at src/team/tmux-session.ts:293
paneId: string;
panePid: number;
sessionName: string;
sessionId: string;
sessionCreated: string;
windowId: string;
windowIndex: string;
/** Present only after the Team owner bootstrap tag has been committed. */
teamPaneOwnerId: string | null;
};
function captureSourcePaneAuthority(paneId: string, expectedTeamPaneOwnerId?: string): SourcePaneAuthority {
const target = paneId.trim();
if (!/^%[0-9]+$/.test(target)) throw new Error(`invalid tmux source pane: ${paneId}`);
const result = runTmuxStructured([
'display-message', '-p', '-t', target,
'#{session_name}\t#{session_id}\t#{session_created}\t#{window_index}\t#{window_id}\t#{pane_id}\t#{pane_pid}',
]);
if (!result.ok) throw new Error(`failed to capture tmux source authority: ${result.stderr}`);
const fields = result.stdout.split('\t');
if (fields.length !== 7) throw new Error('malformed tmux source authority');
const [sessionName, sessionId, sessionCreated, windowIndex, windowId, capturedPaneId, panePid] = fields;
if (!sessionName || !/^\$[0-9]+$/.test(sessionId) || !/^[0-9]+$/.test(sessionCreated)
|| !/^[0-9]+$/.test(windowIndex) || !/^@[0-9]+$/.test(windowId)
|| capturedPaneId !== target || !/^[1-9][0-9]*$/.test(panePid)) {
throw new Error('malformed tmux source authority');
}
const parsedPid = Number(panePid);
if (!Number.isSafeInteger(parsedPid) || parsedPid <= 0) throw new Error('malformed tmux source authority');
const proof = readExactPaneProofSync(target);
if (proof.status === 'unavailable') throw new ExactPaneProofUnavailableError(proof);
if (proof.status !== 'live' || proof.pid !== parsedPid) throw new Error(`tmux pane identity changed: ${target}`);
const ownerResult = runTmuxStructured(['show-option', '-qv', '-p', '-t', target, OMX_TEAM_PANE_OWNER_OPTION]);
if (!ownerResult.ok) throw new Error(`failed to capture tmux pane owner: ${ownerResult.stderr}`);
const teamPaneOwnerId = ownerResult.stdout.trim() || null;
if (teamPaneOwnerId && !/^[A-Za-z0-9._:-]+$/.test(teamPaneOwnerId)) {
throw new Error('malformed tmux pane owner');View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Verify the pane still exists: `tmux display-message -p -t <paneId> '#{pane_id}'` before retrying
- If the tmux server restarted, re-discover pane IDs (all %ids are stale) and rebuild the session
- Check the embedded stderr — 'no such pane'/'lost server' each imply a different recovery path
- Ensure TMUX and TMUX_TMPDIR are set consistently in the environment your process runs in
Example fix
// before
const source = captureSourcePaneAuthority('%7');
// after
if (!runTmuxStructured(['display-message','-p','-t','%7','#{pane_id}']).ok) {
throw new Error('source pane %7 is gone; re-select a live pane');
}
const source = captureSourcePaneAuthority('%7'); Defensive patterns
Strategy: validation
Validate before calling
const ok = runTmuxStructured(['display-message','-p','-t',paneId,'#{pane_id}']);
if (!ok.ok) throw new Error(`pane ${paneId} no longer addressable: ${ok.stderr}`); Type guard
function isAddressablePane(paneId: string): boolean { return /^%[0-9]+$/.test(paneId); } Try / catch
catch (e) { if (/failed to capture tmux source authority/.test(e.message)) { re-discoverPane(); return; } throw e; } Prevention
- Re-resolve pane IDs immediately before capture instead of caching them
- Keep TMUX and TMUX_TMPDIR consistent across spawned processes
- Never reuse pane IDs after a tmux server restart
When it happens
Trigger: Calling captureSourcePaneAuthority (directly or via leaderSource/paneSource/splitSource/hudSource/createTeamSession) with a pane ID that tmux cannot resolve: pane already closed, session killed, tmux server restarted, malformed %pane id that still passed the /^%[0-9]+$/ shape check, or a broken tmux binary/socket (TMUX_TMPDIR mismatch).
Common situations: The source pane was closed by the user or an agent between selection and capture; tmux server was restarted so all pane IDs are stale; SSH session dropped and the tmux socket vanished; TMUX_TMPDIR/TMUX env inherited inconsistently across processes.
Related errors
- shutdown_${scope}_${kind.replaceAll(' ', '_')}_identity_chan
- tmux pane is not proven live: ${normalizedLeaderPaneId}
- invalid auth slot path
- ${label} is not a file: ${path}
- ${label} not found: ${path}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/d9c98917c71b1188.
Report an issue: GitHub.