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
- Retry team startup after fully cleaning the previous/stale team state
- Ensure workerCount matches what the planning API expects and no worker names collide
- Report as a bug if reproducible with a clean state — the planner and the loop should never disagree
- 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
- Validate planned arrays match workerCount before commit
- Never reuse partially-written team state
- Avoid concurrent startups of the same team
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
- failed to initialize team config
- missing worker launch plan for worker-${i}
- Missing notification metadata snapshot for ${notifyPlan.meta
- Missing notification metadata snapshot for ${metadataPath};
- Team mode requires running inside tmux current leader pane
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/ebe520d81b582e20.
Report an issue: GitHub.