Yeachan-Heo/oh-my-codex · critical · Error
canonical_scale_down_config_verification_failed
Error message
canonical_scale_down_config_verification_failed
What it means
After committing the scale-down membership transaction, re-reading the config still shows at least one removable worker present. The committed state does not reflect the removal, indicating a transaction/verification failure.
Source
Thrown at src/team/scaling.ts:2167
index: worker.index,
pane_id: worker.pane_id,
pid: worker.pid ?? null,
})),
resource_workers: removableWorkers.map((worker) => ({
name: worker.name,
worktree_path: worker.worktree_path,
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'View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Check for concurrent processes writing team config and stop them
- Inspect/clear .membership-task-transaction.json and re-run scaleDown to reconcile
- Read the config directly to confirm current membership, then retry removal for remaining workers
Defensive patterns
Strategy: retry
Try / catch
catch (e) {
if ((e as Error).message === 'canonical_scale_down_config_verification_failed') {
await stopConcurrentWriters(team);
return retryScaleDownOnce();
}
throw e;
} Prevention
- Ensure a single writer for team config (no concurrent CLI processes)
- Investigate stuck membership transaction journals promptly
When it happens
Trigger: scaleDown commits membershipTransaction then readTeamConfig returns a config containing a worker in removableWorkerNames.
Common situations: Another writer mutated the config between commit and verification; transaction journal replay overwriting the commit; filesystem caching or torn writes on the config file.
Related errors
- canonical_scale_down_task_verification_failed:${task.id}
- Native hook transaction rollback preserved ${artifact.path}
- canonical_scale_up_rollback_resolved_membership_verification
- scale_down_cleanup_debt_path_missing_parent:${path}
- scale_down_cleanup_debt_path_escape:${path}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/d40d3561a74a0edf.
Report an issue: GitHub.