Yeachan-Heo/oh-my-codex · error · UltragoalError

Blocked ultragoal checkpoint is only for a different complet

Error message

Blocked ultragoal checkpoint is only for a different completed legacy Codex goal unless an aggregate Codex goal is already complete and unreconcilable while the active repo-native microgoal remains in progress.

What it means

The Codex snapshot is 'complete' but it matches this goal's expected objective and is not a safe completed aggregate blocker. A completed matching goal means the work finished, so a blocked checkpoint for it is contradictory — blocked checkpoints on completed Codex goals are only allowed when the completed goal is a different legacy goal, or when an aggregate Codex goal is complete/unreconcilable while the repo-native microgoal remains in progress (isSafeCompletedAggregateBlockerSnapshot).

Source

Thrown at src/ultragoal/artifacts.ts:1850

      plan.updatedAt = now;
      await writePlan(cwd, plan);
      await appendLedger(cwd, {
        ts: now,
        event: 'goal_blocked',
        goalId: goal.id,
        status: goal.status,
        evidence,
        codexGoal: options.codexGoal,
        message: 'Native Codex goal status is blocked for the matching objective; recorded a non-terminal goal_blocked checkpoint. Continue work without treating this as complete or failed; re-check get_goal when the blocker clears.',
      });
      return plan;
    }
    if (snapshot.status !== 'complete') {
      throw new UltragoalError(`Cannot record a blocked ultragoal checkpoint while the existing Codex goal is ${snapshot.status ?? 'unknown'}; strict objective mismatch protection remains required for active or incomplete goals.`);
    }
    const safeCompletedAggregateBlocker = isSafeCompletedAggregateBlockerSnapshot(plan, goal, snapshot, options.evidence);
    if (!safeCompletedAggregateBlocker && blockedSnapshotMatchesExpected) {
      throw new UltragoalError('Blocked ultragoal checkpoint is only for a different completed legacy Codex goal unless an aggregate Codex goal is already complete and unreconcilable while the active repo-native microgoal remains in progress.');
    }
    goal.updatedAt = now;
    if (safeCompletedAggregateBlocker) 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: safeCompletedAggregateBlocker
        ? 'Completed aggregate Codex goal is already terminal while the repo-native microgoal remains in progress; recorded a non-terminal safe-recovery blocker to avoid repeating an impossible checkpoint loop.'
        : undefined,
    });
    return plan;

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Record a 'complete' checkpoint instead — the matching Codex goal is finished
  2. If this is the aggregate-blocker scenario, provide the evidence/preconditions isSafeCompletedAggregateBlockerSnapshot requires (aggregate complete + unreconcilable + microgoal in progress)
  3. Clear or re-create goals so the completed goal is no longer ambiguously matching
Defensive patterns

Strategy: validation

Validate before calling

if (snap.status === 'complete' && blockedSnapshotMatchesExpected && !isSafeCompletedAggregateBlockerSnapshot(plan, goal, snap, evidence)) { recordCompleteInstead(); }

Prevention

When it happens

Trigger: Passing a 'complete' snapshot whose objective matches the current goal, while isSafeCompletedAggregateBlockerSnapshot(plan, goal, snapshot, evidence) returns false.

Common situations: The Codex goal for this ultragoal already completed but the operator tries to record it as blocked; aggregate-mode plans where the aggregate goal completed but the microgoal reconciliation preconditions aren't met.

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


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/17d4500a75f06798. Report an issue: GitHub.