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

missing worker launch policy for worker-${i}

Error message

missing worker launch policy for worker-${i}

What it means

Internal invariant error: for each worker index i (1..workerCount), the precomputed workerLaunchPolicyPlan must contain a policy. If the array is shorter than workerCount or has a hole, startup aborts with this message naming the offending worker.

Source

Thrown at src/team/runtime.ts:3712

        worktreeCreated?: boolean;
      };
      workerTasks: TeamTask[];
      workerRole: string;
      rolePromptContent: string | null;
      instructionsFilePath: string;
      inbox: string;
      trigger: string;
      triggerIntent: TeamReminderIntent;
      initialPrompt?: string;
      workerLaunchArgs: readonly string[];
      workerCli: TeamWorkerCli;
      toolContext: ReturnType<typeof resolveWorktreeToolContext>;
    }>;

    for (let i = 1; i <= workerCount; i++) {
      const workerLaunchPolicy = workerLaunchPolicyPlan[i - 1];
      if (!workerLaunchPolicy) {
        throw new Error(`missing worker launch policy for worker-${i}`);
      }
      const workerName = workerLaunchPolicy.workerName;
      const workerWorkspace = workerWorkspaceByName.get(workerName) ?? { cwd: leaderCwd };
      const workerTasks = allTasks.filter(t => t.owner === workerName);
      const runtimeRole = workerLaunchPolicy.workerRole;
      const rawRolePromptContent = await loadRolePrompt(runtimeRole, join(leaderCwd, '.codex', 'prompts'))
        ?? await loadRolePrompt(runtimeRole, codexPromptsDir());
      const workerLaunchArgs = workerLaunchPolicy.workerLaunchArgs;
      const workerCli = workerLaunchPolicy.workerCli;
      const resolvedWorkerModel = parseTeamWorkerLaunchArgs([...workerLaunchArgs]).modelOverride ?? undefined;
      const rolePromptContent = rawRolePromptContent
        ? composeRoleInstructionsForRole(runtimeRole, rawRolePromptContent, resolvedWorkerModel)
        : null;
      const workerWorktreePath = workerWorkspace.worktreePath ?? undefined;
      const toolContext = resolveWorktreeToolContext({
        cwd: workerWorkspace.cwd,
        scope: 'team',
        repoRoot: workerWorkspace.worktreeRepoRoot ?? leaderCwd,

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Retry team startup after fully cleaning the previous/stale team state
  2. Ensure workerCount matches what the planning API expects and no worker names collide
  3. Report as a bug if reproducible with a clean state — the planner and the loop should never disagree
  4. Check for swallowed errors in the planning phase logs preceding this throw
Defensive patterns

Strategy: validation

Validate before calling

if (workerLaunchPolicyPlan.length !== workerCount || workerLaunchPolicyPlan.some(p => !p)) {
  throw new Error(`planning produced ${workerLaunchPolicyPlan.length} policies for ${workerCount} workers`);
}

Try / catch

try { await startTeam(opts); } catch (e) { if (/^missing worker launch policy/.test(String((e as Error).message))) { /* clean state, retry fresh */ } throw e; }

Prevention

When it happens

Trigger: Passing a workerCount larger than the number of entries produced by the launch policy planning phase; a planning step silently skipping/omitting a worker's policy (e.g., name collision or workspace resolution failure earlier in planning).

Common situations: Mismatch between requested worker count and planned policies after an error was swallowed during planning; race with concurrent team startups; inconsistent sanitized team name causing some plan entries to be dropped.

Related errors


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