Yeachan-Heo/oh-my-codex · error · UltragoalError
Missing --goal-id.
Error message
Missing --goal-id.
What it means
record-review-blockers records final-review blockers against an existing goal, so --goal-id is mandatory to know which goal to block. It is the first of four required flags checked (--goal-id, --title, --objective, --evidence) before recordFinalReviewBlockers runs.
Source
Thrown at src/cli/ultragoal.ts:475
if (!result.accepted) process.exitCode = 1;
return;
}
const proposal = await parseSteeringProposal(rest);
if (!proposal.evidence?.trim?.()) throw new UltragoalError('Missing --evidence.');
if (!proposal.rationale?.trim?.()) throw new UltragoalError('Missing --rationale.');
proposal.source = parseSteeringSource(source, proposal.source);
const result = await steerUltragoal(cwd, proposal, { directiveText: buildSteerDirectiveText(rest) });
printSteerResult(proposal, result, json);
if (!result.accepted) process.exitCode = 1;
return;
}
if (command === 'record-review-blockers') {
const goalId = readValue(rest, '--goal-id');
const title = readValue(rest, '--title');
const objective = readValue(rest, '--objective');
const evidence = readValue(rest, '--evidence');
if (!goalId) throw new UltragoalError('Missing --goal-id.');
if (!title?.trim()) throw new UltragoalError('Missing --title.');
if (!objective?.trim()) throw new UltragoalError('Missing --objective.');
if (!evidence?.trim()) throw new UltragoalError('Missing --evidence.');
const codexGoal = await parseCodexGoalJson(readValue(rest, '--codex-goal-json'));
const result = await recordFinalReviewBlockers(cwd, { goalId, title, objective, evidence, codexGoal });
if (json) printJson({ ok: true, plan: result.plan, blockedGoal: result.blockedGoal, addedGoal: result.addedGoal, summary: summarizeUltragoalPlan(result.plan) });
else {
console.log(`ultragoal final review blockers recorded: ${result.blockedGoal.id} -> review_blocked; added ${result.addedGoal.id}`);
printStatus(result.plan);
}
return;
}
if (command === 'complete' || command === 'complete-goals' || command === 'next' || command === 'start-next') {
const result = await startNextUltragoal(cwd, { retryFailed: hasFlag(rest, '--retry-failed') });
if (!result.goal) {
const handoff = blockedDecisionHandoff(result.plan);
if (json) {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Get the id via `omx ultragoal status` (or --json and jq '.plan.goals[].id') and pass `--goal-id <id>`
- Quote the id: --goal-id "$GOAL_ID" and assert it is set in scripts
Example fix
# before omx ultragoal record-review-blockers --title t --objective o --evidence e # Error: Missing --goal-id. # after omx ultragoal record-review-blockers --goal-id goal-3 --title t --objective o --evidence e
Defensive patterns
Strategy: validation
Validate before calling
if (!goalId) { console.error('--goal-id required; get one from `omx ultragoal status --json`'); process.exit(2); } Type guard
function isGoalId(v: string | undefined): v is string {
return !!v && /^goal(-\w+)?$/.test(v.trim()); // adjust to your id format
} Prevention
- Fetch goal ids from status --json via jq rather than hand-copying
- Quote ids in shell; assert env-provided ids are set
When it happens
Trigger: `omx ultragoal record-review-blockers --title t --objective o --evidence e` with no --goal-id.
Common situations: Assuming the CLI infers the current goal from context (`status`/`next`); id copied from JSON but stripped by shell quoting; goal id renamed between versions.
Related errors
- Missing --kind for structured ultragoal steer.
- Missing brief text. Pass --brief, --brief-file, --from-stdin
- Missing --title.
- Missing --objective.
- Missing --evidence.
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/b52dd909081f18f6.
Report an issue: GitHub.