github/copilot-sdk · error

pipeline(items, ...stages): items must be an array

Error message

pipeline(items, ...stages): items must be an array

What it means

pipeline(items, ...stages) requires the first argument to be an array of items; each item is run through the stages and results are combined. A non-array first argument cannot be fanned out, so it throws immediately before any stage executes.

Solutions

  1. Pass items as an array; spread iterables: pipeline([...mySet], stage).
  2. Convert objects with Object.entries(obj) or Object.values(obj).
  3. Check the argument order: items first, then stage functions.

Example fix

// before
await session.pipeline(userMap, normalize, enrich);
// after
await session.pipeline(Object.values(userMap), normalize, enrich);
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(items)) items = Array.from(items as Iterable<unknown>);

Type guard

const isItems = (v: unknown): v is unknown[] => Array.isArray(v);

Try / catch

try { await session.pipeline(items, ...stages); } catch (e) { if (String(e.message).includes('items must be an array')) await session.pipeline(Array.from(items as never[]), ...stages); else throw e; }

Prevention

When it happens

Trigger: Calling pipeline() with a non-array items value — e.g. a single object, a Map/Set, an iterable, or arguments accidentally reordered so a stage function lands in the items position.

Common situations: Passing an object instead of Object.values(obj)/Object.entries(obj); passing a generator or Set without spreading to an array; refactor that swapped argument order.

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/5e44d4630140f4ca. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/session.ts:215

                    // reported as completed. An ordinary subagent failure never
                    // rejects — it already resolves `null`.
                    if (isFactoryFatalError(error)) {
                        throw error;
                    }
                    return null;
                })
        )
    );
}

async function runFactoryPipeline(
    items: unknown[],
    ...stages: Array<
        (previous: unknown, item: unknown, index: number) => Promise<unknown> | unknown
    >
): Promise<unknown[]> {
    if (!Array.isArray(items)) {
        throw new Error("pipeline(items, ...stages): items must be an array");
    }
    assertFactoryFanoutSize("pipeline", items.length);
    return Promise.all(
        items.map(async (item, index) => {
            let previous = item;
            for (const stage of stages) {
                try {
                    previous = await stage(previous, item, index);
                } catch (error) {
                    // Propagate cancellation and hard runtime failures instead
                    // of mapping them to `null`, so an aborted stage — or one
                    // that hit a resource ceiling or durable-state failure —
                    // does not let the run report success.
                    if (isFactoryFatalError(error)) {
                        throw error;
                    }
                    return null;
                }

View on GitHub (pinned to cd8cf15dc3)