Yeachan-Heo/oh-my-codex · error · Error
canonical_scale_up_rollback_worker_verification_failed:${wor
Error message
canonical_scale_up_rollback_worker_verification_failed:${workerName} What it means
During scale-up rollback, a worker directory that should have been deleted still exists under team state workers/. The message embeds the workerName whose directory survived cleanup.
Source
Thrown at src/team/scaling.ts:990
...(context.workerName && !unresolvedWorkerNames.has(context.workerName) ? [context.workerName] : []),
]);
try {
for (const taskId of createdTaskIds) {
const task = await readTask(sanitized, taskId, leaderCwd);
if (task && unresolvedWorkerNames.has(task.owner ?? '')) continue;
await rm(join(teamStateRoot, 'team', sanitized, 'tasks', `task-${taskId}.json`), { force: true });
}
await Promise.all([...cleanupWorkerNames].map(async (workerName) => {
await rm(join(teamStateRoot, 'team', sanitized, 'workers', workerName), { recursive: true, force: true });
}));
for (const taskId of createdTaskIds) {
const task = await readTask(sanitized, taskId, leaderCwd);
if (task && unresolvedWorkerNames.has(task.owner ?? '')) continue;
if (task) throw new Error(`canonical_scale_up_rollback_task_verification_failed:${taskId}`);
}
for (const workerName of cleanupWorkerNames) {
if (existsSync(join(teamStateRoot, 'team', sanitized, 'workers', workerName))) {
throw new Error(`canonical_scale_up_rollback_worker_verification_failed:${workerName}`);
}
}
} catch (rollbackError) {
cleanupDebt.push(`canonical_cleanup_failed:${String(rollbackError)}`);
}
try {
const contextWorkerName = context.worker?.name ?? context.workerName;
const contextWorktreePath = context.worker?.worktree_path ?? context.worktreePath;
if (contextWorkerName && contextWorktreePath && !unresolvedWorkerNames.has(contextWorkerName)) {
await removeWorkerWorktreeRootAgentsFile(sanitized, contextWorkerName, teamStateRoot, contextWorktreePath);
}
const unresolvedWorktreePaths = new Set(rollbackWorkers
.filter((worker) => unresolvedWorkerNames.has(worker.name) && typeof worker.worktree_path === 'string')
.map((worker) => resolve(worker.worktree_path as string)));
await rollbackProvisionedWorktrees(provisionedWorktrees.filter((worktree) => !unresolvedWorktreePaths.has(resolve(worktree.worktreePath))));
await Promise.all([...preparedWorkerDirectoryOwner.entries()]
.filter(([, workerName]) => !unresolvedWorkerNames.has(workerName))View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Manually remove the reported worker directory under team state workers/ and retry scaleUp
- Ensure the worker process/pane for that worker is terminated before scaling again
- Check filesystem permissions on the team state root
Defensive patterns
Strategy: retry
Validate before calling
import { existsSync, rmSync } from 'node:fs';
import { join } from 'node:path';
// before retrying, confirm worker dirs are gone
function workerDirsClean(stateRoot: string, team: string, workers: string[]): boolean {
return workers.every((w) => !existsSync(join(stateRoot, 'team', team, 'workers', w)));
} Try / catch
catch (e) {
const m = /canonical_scale_up_rollback_worker_verification_failed:(.+)$/.exec(String((e as Error).message));
if (m) { rmSync(join(stateRoot,'team',team,'workers',m[1]), { recursive: true, force: true }); return retryScaleUp(); }
throw e;
} Prevention
- Terminate worker panes/processes before scaling
- Check directory permissions on the team state root
When it happens
Trigger: scaleUp rollback removes worker directories with rm recursive force, then existsSync still finds the worker directory path present.
Common situations: Filesystem race where a worker process recreates its directory; permission issues blocking deletion; Windows/macOS file locking holding the directory.
Related errors
- canonical_scale_up_rollback_task_verification_failed:${taskI
- cleanupErrors.join(' | ')
- canonical_scale_up_rollback_resolved_membership_verification
- Native hook transaction rollback removal claim failed (${err
- Native hook transaction staged deletion cleanup claim failed
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/b1d21bdd32dbd856.
Report an issue: GitHub.