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

  1. Add a launcherCommand to the worker entry in the orchestration config.
  2. Fix the field name typo so it is exactly launcherCommand.
  3. Use a worker type/name the orchestrator recognizes so its default launcher applies.
  4. 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

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


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)