{"record":{"id":"5e44d4630140f4ca","repo":"github/copilot-sdk","slug":"pipeline-items-stages-items-must-be-an-array","errorCode":null,"errorMessage":"pipeline(items, ...stages): items must be an array","messagePattern":"pipeline\\(items, \\.\\.\\.stages\\): items must be an array","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodejs/src/session.ts","lineNumber":215,"sourceCode":"                    // reported as completed. An ordinary subagent failure never\n                    // rejects — it already resolves `null`.\n                    if (isFactoryFatalError(error)) {\n                        throw error;\n                    }\n                    return null;\n                })\n        )\n    );\n}\n\nasync function runFactoryPipeline(\n    items: unknown[],\n    ...stages: Array<\n        (previous: unknown, item: unknown, index: number) => Promise<unknown> | unknown\n    >\n): Promise<unknown[]> {\n    if (!Array.isArray(items)) {\n        throw new Error(\"pipeline(items, ...stages): items must be an array\");\n    }\n    assertFactoryFanoutSize(\"pipeline\", items.length);\n    return Promise.all(\n        items.map(async (item, index) => {\n            let previous = item;\n            for (const stage of stages) {\n                try {\n                    previous = await stage(previous, item, index);\n                } catch (error) {\n                    // Propagate cancellation and hard runtime failures instead\n                    // of mapping them to `null`, so an aborted stage — or one\n                    // that hit a resource ceiling or durable-state failure —\n                    // does not let the run report success.\n                    if (isFactoryFatalError(error)) {\n                        throw error;\n                    }\n                    return null;\n                }","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/nodejs/src/session.ts#L197-L233","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass items as an array; spread iterables: pipeline([...mySet], stage).","Convert objects with Object.entries(obj) or Object.values(obj).","Check the argument order: items first, then stage functions."],"exampleFix":"// before\nawait session.pipeline(userMap, normalize, enrich);\n// after\nawait session.pipeline(Object.values(userMap), normalize, enrich);","handlingStrategy":"validation","validationCode":"if (!Array.isArray(items)) items = Array.from(items as Iterable<unknown>);","typeGuard":"const isItems = (v: unknown): v is unknown[] => Array.isArray(v);","tryCatchPattern":"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; }","preventionTips":["Convert Maps/Sets/objects to arrays (Array.from, Object.values) before pipelining.","Type the items parameter as unknown[] to catch mistakes at compile time.","Double-check argument order when using spread stage lists."],"tags":["argument-type","pipeline","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}