affaan-m/ECC · error

Worker ${index + 1} is missing a task

Error message

Worker ${index + 1} is missing a task

What it means

Thrown inside the workers.map loop in buildOrchestrationPlan() when a worker entry is null/undefined or its task field is missing, not a string, or only whitespace. The task string is what gets written to task_file inside the worktree and ultimately drives the worker agent, so an empty task would produce an empty instruction file. The 1-based index in the message identifies which worker in the array failed.

Source

Thrown at scripts/lib/tmux-worktree-orchestrator.js:196

  const workers = Array.isArray(config.workers) ? config.workers : [];
  const globalSeedPaths = normalizeSeedPaths(config.seedPaths, repoRoot);
  const sessionName = slugify(config.sessionName || repoName, 'session');
  const worktreeRoot = path.resolve(config.worktreeRoot || path.dirname(repoRoot));
  const coordinationRoot = path.resolve(
    config.coordinationRoot || path.join(repoRoot, '.orchestration')
  );
  const coordinationDir = path.join(coordinationRoot, sessionName);
  const baseRef = config.baseRef || 'HEAD';
  const defaultLauncher = config.launcherCommand || '';

  if (workers.length === 0) {
    throw new Error('buildOrchestrationPlan requires at least one worker');
  }

  const seenSlugs = new Set();
  const workerPlans = workers.map((worker, index) => {
    if (!worker || typeof worker.task !== 'string' || worker.task.trim().length === 0) {
      throw new Error(`Worker ${index + 1} is missing a task`);
    }

    const workerName = worker.name || `worker-${index + 1}`;
    const workerSlug = slugify(workerName, `worker-${index + 1}`);

    if (seenSlugs.has(workerSlug)) {
      throw new Error(`Workers must have unique slugs — duplicate: ${workerSlug}`);
    }
    seenSlugs.add(workerSlug);

    const branchName = `orchestrator-${sessionName}-${workerSlug}`;
    const worktreePath = path.join(worktreeRoot, `${repoName}-${sessionName}-${workerSlug}`);
    const workerCoordinationDir = path.join(coordinationDir, workerSlug);
    const taskFilePath = path.join(workerCoordinationDir, 'task.md');
    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);

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Give every worker a non-empty task string: { name: 'alpha', task: 'refactor the auth module' }.
  2. Filter or reject malformed workers before calling buildOrchestrationPlan: workers = workers.filter(w => w?.task?.trim()).
  3. Validate upstream with a schema (zod / ajv) so the error surfaces at config load, not deep in the orchestrator.
  4. Use the index in the message to find the offending entry — it is 1-based.

Example fix

// before
workers: [
  { name: 'alpha', launcherCommand: 'claude' },   // no task
  { name: 'beta', task: 'fix tests' },
]
// -> Worker 1 is missing a task

// after
workers: [
  { name: 'alpha', task: 'refactor auth module', launcherCommand: 'claude' },
  { name: 'beta', task: 'fix tests' },
]
Defensive patterns

Strategy: validation

Validate before calling

function cleanWorkers(workers) {
  return (workers || []).filter(w =>
    w && typeof w.task === 'string' && w.task.trim().length > 0
  );
}

config.workers = cleanWorkers(config.workers);
if (config.workers.length === 0) throw new Error('All workers missing task');

Type guard

function isWorkerWithTask(value) {
  return !!value &&
    typeof value === 'object' &&
    typeof value.task === 'string' &&
    value.task.trim().length > 0;
}

Try / catch

try {
  buildOrchestrationPlan(config);
} catch (error) {
  if (/is missing a task/.test(error.message)) {
    config.workers = config.workers.filter(isWorkerWithTask);
    buildOrchestrationPlan(config);
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: config.workers = [{ name: 'alpha' }] (task omitted); config.workers = [{ task: ' ' }]; config.workers = [{ task: 42 }] (number, not string); config.workers = [null, { task: '...' }] (first entry is null); a worker built from a partial JSON payload where the task field was renamed.

Common situations: A YAML workers list where one entry has only a name and the task lives under a different key (e.g. 'prompt'); CLI argument parsing drops the task when it contains shell metacharacters; an LLM-generated config forgets the field; programmatic builders that conditionally include the task and skip it on a code path.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/b9524fc6697662db. Report an issue: GitHub.