Yeachan-Heo/oh-my-codex · error · Error
--to must be ralplan or ultragoal.
Error message
--to must be ralplan or ultragoal.
What it means
The `autopilot advance` command only supports transitioning to two named phases: ralplan and ultragoal. Any other --to value is rejected.
Source
Thrown at src/cli/autopilot.ts:145
else stdout(instruction(initialized));
return;
}
const state = await readAutopilot(cwd, sessionId);
if (!state) throw new Error('No Autopilot state found. Run `omx autopilot start --task <text>` first.');
if (command === 'status' || command === 'next') {
const nextInstruction = instruction(state);
const skippedGates = skippedGateReport(state as unknown as Record<string, unknown>);
if (json) stdout(JSON.stringify({ state, instruction: nextInstruction }));
else if (command === 'next') stdout(nextInstruction);
else stdout([skippedGates ?? `autopilot: ${state.current_phase}`, nextInstruction].join('\n'));
return;
}
if (command === 'advance') {
const to = value(rest, '--to');
if (to !== 'ralplan' && to !== 'ultragoal') throw new Error('--to must be ralplan or ultragoal.');
const rawHandoff = value(rest, '--handoff-json');
if (!rawHandoff) throw new Error('Missing --handoff-json.');
const handoff = await jsonInput(rawHandoff);
assertBoundHandoffIdentity(handoff, cwd, sessionId);
const updated = await updateAutopilotPipelineState({
...handoff,
active: true,
current_phase: to,
}, cwd, sessionId);
if (json) stdout(JSON.stringify({ ok: true, state: updated, instruction: instruction(updated) }));
else stdout(instruction(updated));
return;
}
throw new Error(`Unknown autopilot command: ${command}\n${AUTOPILOT_HELP}`);
}
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Use exactly `--to ralplan` or `--to ultragoal` (lowercase)
- Run `omx autopilot` with no args to print AUTOPILOT_HELP and confirm supported phase names
- Check spelling/case — the comparison is strict string equality
Example fix
// before omx autopilot advance --to RalPlan --handoff-json h.json // after omx autopilot advance --to ralplan --handoff-json h.json
Defensive patterns
Strategy: validation
Validate before calling
const PHASES = ['ralplan','ultragoal'] as const;
if (!PHASES.includes(to)) throw new UsageError(`--to must be one of ${PHASES.join(', ')}`); Type guard
const isPhase = (v: string): v is 'ralplan'|'ultragoal' => v==='ralplan'||v==='ultragoal';
Try / catch
try { await advance(to); } catch (e) { if (e.message.includes('--to must be')) printSupportedPhases(); else throw e; } Prevention
- Pin phase names as string-literal union types in wrapper code
- Read AUTOPILOT_HELP after version upgrades
When it happens
Trigger: Running `omx autopilot advance --to <x>` where x is not exactly 'ralplan' or 'ultragoal' — e.g. typos like 'ralplans', 'UltraGoal', 'plan', or an arbitrary phase name.
Common situations: Guessing phase names without reading the help text, case mismatches, or copied commands from outdated docs referring to renamed phases.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Missing value for ${flag}.
- --handoff-json must resolve to a JSON object.
- Autopilot handoff session_id does not match the selected ses
- Autopilot handoff workingDirectory does not match the select
- Missing --task.
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/f3d855a708cc2134.
Report an issue: GitHub.