Yeachan-Heo/oh-my-codex · error · Error
Autopilot handoff session_id does not match the selected ses
Error message
Autopilot handoff session_id does not match the selected session.
What it means
Thrown by assertBoundHandoffIdentity() during `autopilot advance` when the handoff JSON contains a session_id string that differs from the currently selected OMX session. This is a safety check that prevents a handoff produced in one session from being applied to a different session.
Source
Thrown at src/cli/autopilot.ts:57
const valueFlags = new Set(['--task', '--session', '--to', '--handoff-json']);
const words: string[] = [];
for (let i = 0; i < args.length; i += 1) {
if (valueFlags.has(args[i])) { i += 1; continue; }
if (!args[i].startsWith('--')) words.push(args[i]);
}
return words.join(' ').trim();
}
async function jsonInput(raw: string): Promise<Record<string, unknown>> {
const text = raw.trim().startsWith('{') ? raw : await readFile(raw, 'utf-8');
const parsed = JSON.parse(text) as unknown;
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('--handoff-json must resolve to a JSON object.');
return parsed as Record<string, unknown>;
}
function assertBoundHandoffIdentity(handoff: Record<string, unknown>, cwd: string, sessionId?: string): void {
if (typeof handoff.session_id === 'string' && handoff.session_id !== sessionId) {
throw new Error('Autopilot handoff session_id does not match the selected session.');
}
if (typeof handoff.workingDirectory === 'string' && handoff.workingDirectory !== cwd) {
throw new Error('Autopilot handoff workingDirectory does not match the selected workspace.');
}
handoff.session_id = sessionId;
handoff.workingDirectory = cwd;
}
async function readAutopilot(cwd: string, sessionId?: string) {
return sessionId
? readModeStateForExplicitSession('autopilot', sessionId, cwd)
: readModeState('autopilot', cwd);
}
/**
* A terminalization that carried skipped gates must never read as clean success. The durable
* marker is the machine token `complete-with-skipped-gates`; this renders the human string and
* names each skipped gate with its missing evidence so the report is actionable.View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Regenerate the handoff from the current session (the session that will consume it) so session_id matches
- Remove or null out the session_id field in the handoff JSON — the check only applies to string values, and assertBoundHandoffIdentity will stamp the correct current sessionId
- Verify the selected session with the session status command before advancing and switch to the session the handoff was created for
Example fix
// before
{"session_id":"sess-old","task":"..."}
// after
{"task":"..."} // session_id gets stamped from the current session Defensive patterns
Strategy: validation
Validate before calling
const h = JSON.parse(fs.readFileSync(handoffPath,'utf-8'));
if (typeof h.session_id === 'string' && h.session_id !== currentSessionId) {
delete h.session_id; // let CLI stamp the current session
fs.writeFileSync(handoffPath, JSON.stringify(h));
} Try / catch
try { await advance(handoff); } catch (e) { if (e.message.includes('session_id does not match')) regenerateHandoffFromCurrentSession(); else throw e; } Prevention
- Always produce and consume handoffs within the same session
- Omit session_id from handoff templates so the CLI binds it automatically
When it happens
Trigger: Calling autopilot advance with a handoff payload whose session_id field (a string) does not equal the sessionId of the current session (as resolved from cwd/session selection). Undefined or non-string session_id values pass the check and are overwritten with the current sessionId.
Common situations: Replaying a handoff JSON captured from an earlier run after the session was recreated, running the advance command in a fresh shell where a different session is selected, or hand-editing a handoff file and leaving a stale session_id.
Related errors
- --handoff-json must resolve to a JSON object.
- Autopilot handoff workingDirectory does not match the select
- Missing value for ${flag}.
- Missing --task.
- No Autopilot state found. Run `omx autopilot start --task <t
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/a1b15d1487456cde.
Report an issue: GitHub.