Yeachan-Heo/oh-my-codex · error · UltragoalError
Cannot add a goal to an already completed aggregate ultragoa
Error message
Cannot add a goal to an already completed aggregate ultragoal plan; start a new plan for post-terminal work.
What it means
addUltragoalGoal rejects additions to a plan whose aggregateCompletion.status is 'complete'. Once the aggregate ultragoal is terminal, the plan is considered closed and post-terminal work must go into a new plan.
Source
Thrown at src/ultragoal/artifacts.ts:1177
title,
objective,
status: 'pending',
attempt: 0,
createdAt: now,
updatedAt: now,
evidence: options.evidence,
resolvesReviewBlockedGoalId: options.resolvesReviewBlockedGoalId,
};
plan.goals.push(goal);
plan.updatedAt = now;
return goal;
}
export async function addUltragoalGoal(cwd: string, options: AddUltragoalGoalOptions): Promise<{ plan: UltragoalPlan; goal: UltragoalItem }> {
return withUltragoalMutationLock(cwd, async () => {
const plan = await readUltragoalPlanUnderLock(cwd);
if (plan.aggregateCompletion?.status === 'complete') {
throw new UltragoalError('Cannot add a goal to an already completed aggregate ultragoal plan; start a new plan for post-terminal work.');
}
const now = iso(options.now);
const goal = appendGoalToPlan(plan, options);
await writePlan(cwd, plan);
await appendLedger(cwd, {
ts: now,
event: 'goal_added',
goalId: goal.id,
status: goal.status,
evidence: options.evidence,
message: goal.title,
});
return { plan, goal };
});
}
function proposalTargetIds(proposal: UltragoalSteeringProposal): string[] {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Create a fresh plan for the new work: `omx ultragoal create-goals --force` (or in a new plan location) instead of appending
- If the completion was premature/mistaken, edit or re-run the finalize flow to reopen the plan before adding goals
- Add a pre-check in automation: read the plan and skip add when aggregateCompletion.status === 'complete'
Example fix
// before
await addUltragoalGoal(cwd, { objective: 'post-launch tweak' }); // throws 1174
// after
const plan = await readUltragoalPlan(cwd);
if (plan.aggregateCompletion?.status === 'complete') {
await createUltragoalPlan(cwd, { brief: 'post-launch', force: true });
} else {
await addUltragoalGoal(cwd, { objective: 'post-launch tweak' });
} Defensive patterns
Strategy: type-guard
Validate before calling
const plan = await readUltragoalPlan(cwd); const completed = plan.aggregateCompletion?.status === 'complete'; if (!completed) await addUltragoalGoal(cwd, opts);
Type guard
function isPlanOpen(plan: UltragoalPlan): boolean { return plan.aggregateCompletion?.status !== 'complete'; } Try / catch
try { await addUltragoalGoal(cwd, opts); } catch (e) { if (e instanceof UltragoalError && e.message.includes('already completed')) { await createUltragoalPlan(cwd, { brief: 'post-terminal', force: true }); } else throw e; } Prevention
- Check aggregateCompletion.status before appending goals
- Treat 'complete' as terminal: plan new work in a new plan
- Guard scheduled/automated adders with the open-plan check
When it happens
Trigger: Calling addUltragoalGoal on a plan that was previously finalized with aggregate completion marked complete — e.g. continuing to append goals after a release/milestone was closed out.
Common situations: Reopening work after a milestone was marked complete; automation that appends goals on a schedule hitting an already-finalized repo; two teams sharing a repo where one finalized the plan.
Related errors
- Refusing a durable ultragoal mutation before writable lifecy
- Cannot record a ${options.status} checkpoint for ${goal.id}
- Autoresearch goal ${mission.slug} is already complete; creat
- autoresearch_resume_terminal_run
- detached leader interrupted before release: ${interrupted}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/baeacb3feec963c0.
Report an issue: GitHub.