Yeachan-Heo/oh-my-codex · critical · Error
bound setup finalization denied: ${finalization.cleanup.comp
Error message
bound setup finalization denied: ${finalization.cleanup.comparison?.reason ?? "unknown reason"} What it means
When bound setup fails, the leader attempts to finalize/close the launch binding once; if finalization is denied (binding state comparison mismatch), this wrapped error is thrown instead of the underlying failure.
Source
Thrown at src/cli/index.ts:7065
const nonce = payload.readyPath?.split(".").at(-2) || payload.sessionId;
const contextKey = process.env[OMX_MADMAX_DETACHED_CONTEXT_ENV]?.trim();
const activeRecordPath = contextKey
? madmaxDetachedActiveRecordPath(resolveMadmaxRunsRoot(process.env), contextKey)
: join(omxRoot(payload.cwd), "state", "detached-active-record.json");
let externalInterrupt: NodeJS.Signals | undefined;
try {
const completion = await completePreLaunchSetup(
payload.cwd,
payload.sessionId,
payload.preLaunchOptions.notifyTempContract,
payload.codexHomeOverride,
payload.preLaunchOptions.enableNotifyFallbackAuthority,
payload.preLaunchOptions.worktreeDirty,
);
if (completion.kind === "failure") {
const finalization = await finalizeBoundOnce(binding, "setup-failure", payload.cwd);
if (!finalization.finalized) throw new Error(`bound setup finalization denied: ${finalization.cleanup.comparison?.reason ?? "unknown reason"}`);
throw completion.error;
}
const record: MadmaxDetachedActiveRecord = {
version: 1, context_key: contextKey ?? payload.sessionId!, created_at: new Date().toISOString(),
source_cwd: payload.cwd, argv: [payload.codexCmd], run_dir: process.env.OMX_ROOT ?? payload.cwd,
tmux_session_name: payload.sessionName, session_id: payload.sessionId, tmux_pane_id: pane,
launch_nonce: nonce, leader_pid: process.pid, base_state_root: binding.context.baseStateDir,
lifecycle_phase: "ready",
};
const runtimeBinding = queryMadmaxDetachedRuntimeBinding(record);
ownedRecord = writeMadmaxDetachedActiveRecord(activeRecordPath, {
...record,
...(runtimeBinding ? {
tmux_internal_session_id: runtimeBinding.internalSessionId,
tmux_session_created: runtimeBinding.sessionCreated,
tmux_pane_pid: runtimeBinding.panePid,
} : {}),
});View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Inspect the binding file/state to see why the comparison failed (the reason is embedded in the message)
- Remove the stale binding / active record for that session and retry the launch
- Ensure only one parent CLI orchestrates a given session at a time
Defensive patterns
Strategy: try-catch
Try / catch
try { await runBoundSetup(...); } catch (e) {
if ((e as Error).message.startsWith('bound setup finalization denied')) {
// binding state conflicted: inspect/clear the binding, then re-launch
} else throw e;
} Prevention
- Run one orchestration process per session
- Clean up active records after crashes
- Avoid downgrading CLI versions mid-session
When it happens
Trigger: completeBoundSetup returns kind 'failure' AND finalizeBoundOnce(binding, 'setup-failure', cwd) reports finalized=false, i.e. the binding's expected state no longer matches (already finalized, taken over, or mutated by another process).
Common situations: Two CLI processes racing over the same session binding, a leftover binding file from a previous crashed run, or clock/state version skew after an upgrade.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- invalid auth slot path
- ${label} is not a file: ${path}
- Refusing to overwrite existing ${repoRelative(cwd, missionPa
- [api] failed to launch native binary: executable not found (
- preLaunch ${completion.operation} failed
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/e1740ce8d2a91453.
Report an issue: GitHub.