github/copilot-sdk · error

parallel() expects an array of functions, not promises…

Error message

parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)

What it means

parallel() requires an array of zero-argument functions (thunks) so it controls when each task starts. Passing an array whose elements are not functions is rejected up front. The message specifically calls out the most common mistake: passing already-started promises instead of thunks.

Solutions

  1. Pass an array of functions: parallel(() => agent(...), () => agent(...)).
  2. Ensure the argument is an array, not a single promise or value.
  3. If work is already started as promises, either keep Promise.all or convert to deferred thunks.

Example fix

// before
await session.parallel(agent(taskA), agent(taskB));
// after
await session.parallel([() => agent(taskA), () => agent(taskB)]);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(tasks)) throw new TypeError('parallel() needs an array of thunks');

Type guard

const isThunks = <T>(v: unknown): v is Array<() => T | Promise<T>> => Array.isArray(v) && v.every((x) => typeof x === 'function');

Try / catch

try { await session.parallel(tasks); } catch (e) { if (String(e.message).includes('Wrap each call')) console.error('Pass () => fn(), not fn()'); else throw e; }

Prevention

When it happens

Trigger: Calling parallel() with a non-array value (e.g. undefined, a single promise), or with an array of promises/awaited results instead of () => ... wrappers.

Common situations: Migrating from Promise.all style code: tasks.map(task => task.run()) already starts the work and yields promises; accidentally spreading or forgetting the wrapper arrow around agent(...) calls.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/91763dea8b755438. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/session.ts:178

    );
}

const FACTORY_LOG_FLUSH_DELAY_MS = 10;
const MAX_FACTORY_FANOUT_ITEMS = 4096;

function assertFactoryFanoutSize(kind: "parallel" | "pipeline", size: number): void {
    if (size > MAX_FACTORY_FANOUT_ITEMS) {
        throw new Error(
            `${kind}() accepts at most ${MAX_FACTORY_FANOUT_ITEMS} items; got ${size}.`
        );
    }
}

async function runFactoryParallel<TResult>(
    thunks: Array<() => Promise<TResult> | TResult>
): Promise<Array<TResult | null>> {
    if (!Array.isArray(thunks)) {
        throw new Error(
            "parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)"
        );
    }
    assertFactoryFanoutSize("parallel", thunks.length);
    if (thunks.some((thunk) => typeof thunk !== "function")) {
        throw new Error(
            "parallel() expects an array of functions, not promises. Wrap each call: () => agent(...)"
        );
    }
    return Promise.all(
        thunks.map((thunk) =>
            Promise.resolve()
                .then(() => thunk())
                .catch((error) => {
                    // Cancellation and hard runtime failures must propagate out
                    // of the combinator rather than be mapped to a successful
                    // `null`; otherwise an aborted run, or one that hit a
                    // resource ceiling or durable-state failure, could be

View on GitHub (pinned to cd8cf15dc3)