Yeachan-Heo/oh-my-codex · error · Error
bound session retained close failed: ${closeEvidence.error?.
Error message
bound session retained close failed: ${closeEvidence.error?.message ?? "unknown error"} What it means
During post-launch handling, closing the retained launch session binding (closeLaunchSessionBindingOnce) returned status 'failed', and the error message is surfaced (or 'unknown error' if absent).
Source
Thrown at src/cli/index.ts:7391
context: buildNativeHookBaseContext(cwd, sessionId, normalizedEvent, {
project_path: cwd,
project_name: basename(cwd),
duration_ms: durationMs,
reason: "session_exit",
status: normalizedEvent === "failed" ? "failed" : "finished",
...(process.exitCode !== undefined
? { exit_code: process.exitCode }
: {}),
...(errorSummary ? { error_summary: errorSummary } : {}),
}),
});
} catch (err) {
logCliOperationFailure(err);
// Non-fatal
}
const closeEvidence = await closeLaunchSessionBindingOnce(binding);
if (closeEvidence.status === "failed") {
throw new Error(`bound session retained close failed: ${closeEvidence.error?.message ?? "unknown error"}`);
}
}
export async function runDetachedSessionPostLaunch(
cwd: string,
sessionId: string,
projectLocalCodexHomeForCleanup?: string,
runtimeCodexHomeForCleanup?: string,
releaseMarkerPath?: string,
): Promise<void> {
// The detached child is intentionally unbound: it must never perform parent
// pointer finalization or cleanup after the release barrier. It still owns
// every non-pointer terminal lifecycle responsibility.
const failures: unknown[] = [];
const strict = async (operation: () => Promise<unknown>): Promise<void> => {
try { await operation(); } catch (error) { failures.push(error); }
};
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Read the embedded error message to identify the underlying cause (usually a file or state issue)
- Remove/repair the stale binding artifact for that session and re-run the close/cleanup command
- Avoid running multiple cleanup commands against the same session simultaneously
Defensive patterns
Strategy: try-catch
Try / catch
try { await finalize(); } catch (e) {
if ((e as Error).message.startsWith('bound session retained close failed')) { /* read embedded cause, clear stale binding, retry once */ }
} Prevention
- Serialize cleanup commands per session
- Back up binding files before manual edits
- Report persistent close failures with the embedded message
When it happens
Trigger: closeLaunchSessionBindingOnce fails on I/O (binding file removed/locked) or on a state comparison mismatch while finalizing the retained binding.
Common situations: Concurrent CLI invocations finalizing the same binding, or a partially corrupted binding file after a crash mid-write.
Related errors
- preLaunch setup finalization failed
- preLaunch ${completion.operation} failed
- detached leader authority missing before tmux mutation
- bound setup finalization denied: ${finalization.cleanup.comp
- detached child process group did not disappear after forced
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/938b655f7571fcb2.
Report an issue: GitHub.