{"record":{"id":"6eb4944b8cd7c827","repo":"Yeachan-Heo/oh-my-codex","slug":"detached-active-record-does-not-bind-the-ready-lea","errorCode":null,"errorMessage":"detached active record does not bind the ready leader","messagePattern":"detached active record does not bind the ready leader","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/cli/index.ts","lineNumber":6693,"sourceCode":"          },\n          updateNameMetadata: async () => {\n            const state = await readSessionState(cwd, detachedSelectedStateEnv);\n            if (state?.session_id !== sessionId || state.tmux_session_name !== sessionName) {\n              throw new Error(\"detached session-name metadata was not committed by the leader\");\n            }\n            return \"committed-released\";\n          },\n          updatePaneMetadata: async (_binding, pane) => {\n            const state = await readSessionState(cwd, detachedSelectedStateEnv);\n            if (state?.session_id !== sessionId || state.tmux_pane_id !== pane) {\n              throw new Error(\"detached pane metadata was not committed by the leader\");\n            }\n            return \"committed-released\";\n          },\n          publishActiveRecord: async () => {\n            const activeRecordPath = contextKey ? madmaxDetachedActiveRecordPath(runsRoot, contextKey) : join(omxRoot(cwd), \"state\", \"detached-active-record.json\");\n            const record = readMadmaxDetachedActiveRecord(activeRecordPath);\n            if (!record || record.launch_nonce !== detachedLaunchNonce || record.leader_pid !== detachedLeaderPid || record.session_id !== sessionId || record.tmux_session_name !== sessionName || record.tmux_pane_id !== detachedLeaderPaneId) throw new Error(\"detached active record does not bind the ready leader\");\n            const bytes = readFileSync(activeRecordPath, \"utf-8\");\n            return { bytes, digest: createHash(\"sha256\").update(bytes).digest(\"hex\"), nonce: detachedLaunchNonce };\n          },\n          finalizeSetupFailure: async () => {},\n          releaseBarrier: async () => {\n            if (!detachedLeaderPid) throw new Error(\"detached leader PID missing before release\");\n            publishDetachedReleaseMarker(releaseMarkerPath, detachedLaunchNonce, sessionId, sessionName, detachedLeaderPid, detachedHudAuthority ?? undefined);\n          },\n          abortAndAwaitFinalization: async () => {\n            // The leader has the retained binding. Publishing abort is the only\n            // outer action permitted after a D9 write failure; a mismatched or\n            // missing report leaves every artifact and the tmux session intact.\n            if (!detachedLeaderPid) {\n              rollbackFromPreReportAuthority = detachedLeaderAuthority !== null;\n              return { acknowledged: false, rollbackAuthorized: rollbackFromPreReportAuthority };\n            }\n            const current = readDetachedLeaderReport(releaseMarkerPath);\n            if (current?.nonce === detachedLaunchNonce && current.sessionId === sessionId &&","sourceCodeStart":6675,"sourceCodeEnd":6711,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/index.ts#L6675-L6711","documentation":"Before publishing, OMX reads the detached active record (per-context or default state/detached-active-record.json) and requires every identity field — launch_nonce, leader_pid, session_id, tmux_session_name, tmux_pane_id — to match the ready leader. Any missing record or mismatched field aborts, since publishing a record that binds the wrong session would misroute later clients.","triggerScenarios":"readMadmaxDetachedActiveRecord returns null (leader never wrote the record) or a record with any field diverging from the current launch — stale record from a prior launch, leader crash before publishing, context key selecting a different record path, or split/racing processes overwriting the record.","commonSituations":"Relaunching after crashes without cleaning state; madmax/multi-context setups where contextKey resolution differs between leader and validator; concurrent detached launches; disk issues dropping the leader's write.","solutions":["Remove state/detached-active-record.json (and any context-keyed variants) plus release markers, then relaunch","Ensure contextKey/runsRoot resolution is identical between the leader environment and the outer launch (consistent env vars)","Serialize detached launches per context","If persistent, dump the record file and compare each field against the current launch values to find the divergent writer"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"const record = readMadmaxDetachedActiveRecord(activeRecordPath);\nconst binds = record && record.launch_nonce === nonce && record.leader_pid === pid && record.session_id === sid && record.tmux_session_name === name && record.tmux_pane_id === pane;\nif (!binds) await cleanStaleDetachedState();","typeGuard":"function recordBindsLeader(r: any, l: { nonce: string; pid: number; sid: string; name: string; pane: string }): boolean {\n  return !!r && r.launch_nonce === l.nonce && r.leader_pid === l.pid && r.session_id === l.sid && r.tmux_session_name === l.name && r.tmux_pane_id === l.pane;\n}","tryCatchPattern":"try { establish(); } catch (e) { if (/active record does not bind/.test(e.message)) { await cleanStaleDetachedState(); return establish(); } throw e; }","preventionTips":["Delete detached-active-record.json and markers after crashed launches","Keep contextKey/runsRoot env identical on both sides of the launch","One detached launch per context at a time"],"tags":["detached-launch","active-record","identity-binding","stale-state"],"backgroundTag":"stale-state-mismatch","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}