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
- Give every worker a non-empty task string: { name: 'alpha', task: 'refactor the auth module' }.
- Filter or reject malformed workers before calling buildOrchestrationPlan: workers = workers.filter(w => w?.task?.trim()).
- Validate upstream with a schema (zod / ajv) so the error surfaces at config load, not deep in the orchestrator.
- 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
- Validate each worker object with a schema (zod / ajv) at config load.
- Use the 1-based index in the message to locate the offending entry quickly.
- Treat missing task as a config error, not a defaultable field.
- In tests, build workers from a factory that always sets task.
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
- launcherCommand must be a non-empty string
- Seed path does not exist in repoRoot: ${seedPath}
- buildOrchestrationPlan requires at least one worker
- Worker ${workerName} is missing a launcherCommand
- Invalid mode "${mode}". Allowed modes: ${allowedModes.join('
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/b9524fc6697662db.
Report an issue: GitHub.