affaan-m/ECC · error · Error
Worker is missing a launcherCommand
Error message
Worker ${workerName} is missing a launcherCommand What it means
Each worker plan needs a command that tmux will use to launch the worker process. After resolving the launcher from worker config (with defaults), buildOrchestrationPlan throws if no launcherCommand was resolved, because a worktree would be created with nothing to run in it.
Solutions
- Add a launcherCommand to the worker entry in the orchestration config.
- Fix the field name typo so it is exactly launcherCommand.
- Use a worker type/name the orchestrator recognizes so its default launcher applies.
- Verify the value is non-empty — an empty string may also fail the !launcherCommand check depending on how it's resolved.
Example fix
// before
{ name: 'reviewer' }
// after
{ name: 'reviewer', launcherCommand: 'claude' } Defensive patterns
Strategy: validation
Validate before calling
for (const w of config.workers) {
if (typeof w.launcherCommand !== 'string' || w.launcherCommand.trim() === '') {
throw new Error(`worker '${w.name}' needs a non-empty launcherCommand`);
}
} Type guard
const hasLauncher = (w) => typeof w === 'object' && w !== null && typeof w.launcherCommand === 'string' && w.launcherCommand.length > 0;
Try / catch
try {
const plan = buildOrchestrationPlan(config);
} catch (err) {
const m = err.message.match(/Worker (.+) is missing a launcherCommand/);
if (m) {
console.error(`Add launcherCommand to worker '${m[1]}' in the config`);
return;
}
throw err;
} Prevention
- Validate worker entries with a schema (zod) requiring launcherCommand at config load time
- Spell the field exactly launcherCommand (no launchCommand)
- Only use worker types the orchestrator documents as having default launchers
- Add a dry-run/validate subcommand to check the plan without executing
When it happens
Trigger: Calling plan() with a worker entry that defines neither a launcherCommand nor matches any default launcher rule (e.g. no recognized agent type), leaving launcherCommand undefined/null.
Common situations: Adding a new worker to the config with a custom role but forgetting the launcherCommand field; a typo in the field name (launchCommand vs launcherCommand); using a worker type the orchestrator has no default launcher for.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Announcements discussion category is required
- Canonical session snapshot requires session.sourceTarget to…
- Canonical session snapshot requires session to be an object
- Canonical session snapshot requires workers to be an array
- Choose at least one guided harness: Claude, Codex, or Kimi.
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/30383caad1d46847.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/tmux-worktree-orchestrator.js:229
const handoffFilePath = path.join(workerCoordinationDir, 'handoff.md');
const statusFilePath = path.join(workerCoordinationDir, 'status.md');
const launcherCommand = worker.launcherCommand || defaultLauncher;
const workerSeedPaths = normalizeSeedPaths(worker.seedPaths, repoRoot);
const seedPaths = normalizeSeedPaths([...globalSeedPaths, ...workerSeedPaths], repoRoot);
const templateVariables = buildTemplateVariables({
branch_name: branchName,
handoff_file: handoffFilePath,
repo_root: repoRoot,
session_name: sessionName,
status_file: statusFilePath,
task_file: taskFilePath,
worker_name: workerName,
worker_slug: workerSlug,
worktree_path: worktreePath
});
if (!launcherCommand) {
throw new Error(`Worker ${workerName} is missing a launcherCommand`);
}
const gitArgs = ['worktree', 'add', '-b', branchName, worktreePath, baseRef];
return {
branchName,
coordinationDir: workerCoordinationDir,
gitArgs,
gitCommand: formatCommand('git', gitArgs),
handoffFilePath,
launchCommand: renderTemplate(launcherCommand, templateVariables),
repoRoot,
sessionName,
seedPaths,
statusFilePath,
task: worker.task.trim(),
taskFilePath,
workerName,View on GitHub (pinned to 8321021c54)