Yeachan-Heo/oh-my-codex · error · UltragoalError
Cannot record a blocked checkpoint for ${goal.id} while it i
Error message
Cannot record a blocked checkpoint for ${goal.id} while it is ${goal.status}; start or resume the ultragoal before recording a non-terminal blocker. What it means
A 'blocked' checkpoint was requested for a goal whose status is not 'in_progress'. Non-terminal blockers may only be recorded against a goal that has been started or resumed; a pending/complete/failed goal cannot accept a blocked checkpoint.
Source
Thrown at src/ultragoal/artifacts.ts:1795
plan.updatedAt = now;
await writePlan(cwd, plan);
await appendLedger(cwd, { ts: now, event: 'goal_started', goalId: next.id, status: next.status, message: `Attempt ${next.attempt}` });
return { plan, goal: next, resumed: false, done: false };
});
}
export async function checkpointUltragoal(cwd: string, options: CheckpointOptions): Promise<UltragoalPlan> {
return withUltragoalMutationLock(cwd, async () => {
const plan = await readUltragoalPlanUnderLock(cwd);
const goal = plan.goals.find((candidate) => candidate.id === options.goalId);
if (!goal) throw new UltragoalError(`Unknown ultragoal id: ${options.goalId}`);
if (plan.aggregateCompletion?.status === 'complete' && options.status !== 'complete') {
throw new UltragoalError(`Cannot record a ${options.status} checkpoint for ${goal.id} after the aggregate ultragoal plan is complete; the terminal aggregate receipt is immutable.`);
}
const now = iso(options.now);
if (options.status === 'blocked') {
if (goal.status !== 'in_progress') {
throw new UltragoalError(`Cannot record a blocked checkpoint for ${goal.id} while it is ${goal.status}; start or resume the ultragoal before recording a non-terminal blocker.`);
}
const snapshot = options.codexGoal === undefined ? null : parseCodexGoalSnapshot(options.codexGoal);
if (snapshot?.unavailableReason === 'db_schema_context_error') {
goal.updatedAt = now;
goal.failureReason = assertNonEmpty(options.evidence, '--evidence');
plan.activeGoalId = goal.id;
plan.updatedAt = now;
await writePlan(cwd, plan);
await appendLedger(cwd, {
ts: now,
event: 'goal_blocked',
goalId: goal.id,
status: goal.status,
evidence: options.evidence,
codexGoal: options.codexGoal,
message: 'Codex get_goal was unavailable due to a DB/schema/context error; strict completion reconciliation is deferred until get_goal works.',
});
return plan;View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Start/resume the goal first (record an in_progress checkpoint), then record the blocked checkpoint
- If the goal already reached a terminal state, record the appropriate terminal checkpoint instead of 'blocked'
- Fix workflow ordering so 'start' always precedes 'blocked' reporting
Defensive patterns
Strategy: validation
Validate before calling
const goal = plan.goals.find(g => g.id === options.goalId);
if (options.status === 'blocked' && goal.status !== 'in_progress') throw new Error('start the goal before blocking'); Type guard
const canBlock = (goal: UltragoalItem) => goal.status === 'in_progress';
Prevention
- Enforce start-before-block ordering in orchestration
- Check goal.status before choosing checkpoint status
When it happens
Trigger: Calling checkpointUltragoal with status 'blocked' when goal.status is 'pending' (never started), 'complete', 'failed', or 'review_blocked'.
Common situations: Automation recording blockers before the start step ran; retrying a blocked report after the goal already failed or completed; out-of-order workflow steps.
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
- Cannot record a blocked ultragoal checkpoint while the exist
- Unknown ultragoal id: ${options.goalId}
- Cannot record a ${options.status} checkpoint for ${goal.id}
- Blocked ultragoal checkpoints require either a get_goal snap
- Blocked ultragoal checkpoint objective mismatch: expected on
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/b429a4c549ab887e.
Report an issue: GitHub.