Yeachan-Heo/oh-my-codex · error · Error
canonical_scale_down_task_verification_failed:${task.id}
Error message
canonical_scale_down_task_verification_failed:${task.id} What it means
After scale-down, a reconciled task still references a removed worker as owner or claim owner, meaning task reassignment did not take effect. Message embeds the task.id.
Source
Thrown at src/team/scaling.ts:2174
worktree_repo_root: worker.worktree_repo_root,
worktree_branch: worker.worktree_branch,
worktree_detached: worker.worktree_detached,
worktree_created: worker.worktree_created,
team_state_root: worker.team_state_root,
})),
};
await writeAtomic(cleanupDebtPath, JSON.stringify(cleanupDebtBase, null, 2));
await commitTeamMembershipTaskTransaction(sanitized, leaderCwd, membershipTransaction);
const committed = await readTeamConfig(sanitized, leaderCwd);
if (!committed || committed.workers.some((worker) => removableWorkerNames.has(worker.name))) {
throw new Error('canonical_scale_down_config_verification_failed');
}
config.workers = committed.workers;
config.worker_count = committed.worker_count;
for (const task of reconciledTasks) {
const reconciled = await readTask(sanitized, task.id, leaderCwd);
if (reconciled && (removableWorkerNames.has(reconciled.owner ?? '') || removableWorkerNames.has(reconciled.claim?.owner ?? ''))) {
throw new Error(`canonical_scale_down_task_verification_failed:${task.id}`);
}
}
// PID-less rollback records are cleanup debt, not effect authority. A
// fresh gone proof may resolve one, but a live or unavailable proof
// must remain debt rather than letting teardown adopt its current PID.
const pinnedPaneWorkers = removableWorkers.filter((worker): worker is WorkerInfo & {
pane_id: string;
pid: number;
} => (
typeof worker.pane_id === 'string'
&& /^%\d+$/.test(worker.pane_id)
&& typeof worker.pid === 'number'
&& Number.isSafeInteger(worker.pid)
&& worker.pid > 0
));
const unpinnedPaneWorkers = removableWorkers.filter((worker) => (
typeof worker.pane_id === 'string'View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Inspect the reported task file and manually clear/reassign the owner and claim fields
- Ensure the removed workers' processes are terminated before scaling down
- Re-run scaleDown to reconcile remaining task ownership
Defensive patterns
Strategy: retry
Try / catch
catch (e) {
const m = /canonical_scale_down_task_verification_failed:(.+)$/.exec(String((e as Error).message));
if (m) { await reassignTaskOwner(team, m[1]); return retryScaleDown(); }
throw e;
} Prevention
- Terminate worker processes before scale-down so they cannot re-claim tasks
- Re-run scale-down to let reconciliation finish task reassignment
When it happens
Trigger: scaleDown re-reads each reconciled task; readTask returns a task whose owner or claim.owner is in removableWorkerNames.
Common situations: Concurrent worker writing/claiming its task during teardown; task file rewritten between reassignment and verification; transaction journal not applied to task files.
Related errors
- canonical_scale_down_config_verification_failed
- canonical_scale_up_rollback_task_verification_failed:${taskI
- scale_down_cleanup_debt_path_missing_parent:${path}
- scale_down_cleanup_debt_path_escape:${path}
- scale_down_cleanup_debt_invalid_team_state_root:${worker.nam
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/91f23fce8a293672.
Report an issue: GitHub.