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

Worker ${workerName} not found in team

Error message

Worker ${workerName} not found in team

What it means

Thrown when the requested workerName does not match any entry in config.workers for the team. Assignment requires an existing, configured worker.

Source

Thrown at src/team/runtime.ts:4706

    const task = await readTask(sanitized, taskId, cwd);
    if (!task) throw new Error(`Task ${taskId} not found`);
  const manifest = await readTeamManifestV2(sanitized, cwd);
  const governance = resolveGovernancePolicy(manifest?.governance);

  if (governance.delegation_only && workerName === 'leader-fixed') {
    throw new Error('delegation_only_violation');
  }

  if (governance.plan_approval_required && task.requires_code_change === true) {
    const approved = await isTaskApprovedForExecution(sanitized, taskId, cwd);
    if (!approved) {
      throw new Error('plan_approval_required');
    }
  }
  const config = await readTeamConfig(sanitized, cwd);
  if (!config) throw new Error(`Team ${sanitized} not found`);
  const workerInfo = config.workers.find(w => w.name === workerName);
  if (!workerInfo) throw new Error(`Worker ${workerName} not found in team`);
  const dispatchPolicy = resolveDispatchPolicy(manifest?.policy, config.worker_launch_mode);

  const claim = await claimTask(sanitized, taskId, workerName, task.version ?? 1, cwd);
  if (!claim.ok) {
    if (claim.error === 'blocked_dependency') {
      throw new Error(`blocked_dependency:${(claim.dependencies ?? []).join(',')}`);
    }
    throw new Error(claim.error);
  }

  try {
    // Retry dispatch up to 2 times to handle trust prompts during assignment (fixes #393).
    const approvedExecutionState = await resolvePersistedApprovedTeamExecutionContinuityState(
      sanitized,
      config.leader_cwd ?? cwd,
      config.team_state_root ?? resolveCanonicalTeamStateRoot(config.leader_cwd ?? cwd),
    );
    const persistedUltragoalContext = await readPersistedTeamUltragoalContext(

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Read the team config and dispatch to one of the existing config.workers names
  2. If the worker should exist, re-add/scale up the worker before assignment
  3. Re-check the worker list immediately before dispatch to avoid scale-down races

Example fix

// before
await assignTask(team, taskId, 'worker-3', cwd);

// after
const config = await readTeamConfig(team, cwd);
if (!config?.workers.some(w => w.name === 'worker-3')) throw new Error('worker-3 not in team; refresh worker list');
await assignTask(team, taskId, 'worker-3', cwd);
Defensive patterns

Strategy: validation

Validate before calling

const config = await readTeamConfig(teamName, cwd);
if (!config?.workers.some(w => w.name === workerName)) throw new Error('unknown worker');

Type guard

function isKnownWorker(config: TeamConfig, name: string): boolean {
  return config.workers.some(w => w.name === name);
}

Try / catch

try { await assignTask(t, id, w, cwd); } catch (e) { if (/^Worker .+ not found/.test((e as Error).message)) w = latestWorkerName(t); else throw e; }

Prevention

When it happens

Trigger: Passing a worker name that is not in the team config — e.g. a worker that was removed by scale-down, renamed, or simply mistyped.

Common situations: Stale references to scaled-down workers; worker renamed in config but callers not updated; concurrent scale-down racing with dispatch.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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