{"record":{"id":"413f5e89f0007f3e","repo":"oven-sh/bun","slug":"security-scanner-must-return-an-array-of-advisorie","errorCode":null,"errorMessage":"Security scanner must return an array of advisories","messagePattern":"Security scanner must return an array of advisories","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/install/PackageManager/scanner-entry.ts","lineNumber":106,"sourceCode":"    throw new Error(\"Security scanner must export a 'scanner' object with a version property\");\n  }\n\n  if (scanner.version !== \"1\") {\n    sendAndExit({\n      type: \"error\",\n      code: \"INVALID_VERSION\",\n      message: `Security scanner must be version 1, got version ${scanner.version}`,\n    });\n  }\n\n  if (typeof scanner.scan !== \"function\") {\n    throw new Error(`scanner.scan is not a function, got ${typeof scanner.scan}`);\n  }\n\n  const result = await scanner.scan({ packages });\n\n  if (!Array.isArray(result)) {\n    throw new Error(\"Security scanner must return an array of advisories\");\n  }\n\n  sendAndExit({ type: \"result\", advisories: result });\n} catch (error) {\n  if (!suppressError) {\n    console.error(error);\n  }\n\n  sendAndExit({\n    type: \"error\",\n    code: \"SCAN_FAILED\",\n    message: error instanceof Error ? error.message : \"Unknown error occurred\",\n  });\n}\n","sourceCodeStart":88,"sourceCodeEnd":121,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/install/PackageManager/scanner-entry.ts#L88-L121","documentation":"scanner.scan() ran and resolved, but its resolved value is not an Array. The subprocess requires the advisories list itself — a bare array — not a wrapper object, so this throws and is reported as SCAN_FAILED.","triggerScenarios":"scan returns { advisories: [...] }; returns undefined (async function with a code path that forgets to return); returns a Map or other collection instead of an array.","commonSituations":"Refactor changed the return type; early `return;` on the happy path; wrapping the array \"for future-proofing\"; returning the raw HTTP response object from an advisory-DB fetch.","solutions":["Return the array directly; return [] when the scan is clean","Audit every code path in scan for a missing return","Ensure each entry matches the Bun.Security.Advisory shape — the parent process validates each advisory afterwards (InvalidAdvisoryFormat)"],"exampleFix":"// before\nasync scan({ packages }) { return { advisories: [] }; }\n\n// after\nasync scan({ packages }) { return []; }","handlingStrategy":"type-guard","validationCode":"const result = await scanner.scan({ packages: [] });\nif (!Array.isArray(result)) {\n  throw new Error(\"scan() must resolve to an array of advisories\");\n}","typeGuard":"function isAdvisoryArray(result: unknown): result is unknown[] {\n  return Array.isArray(result);\n}","tryCatchPattern":null,"preventionTips":["Type scan's return as Promise<Advisory[]> in the scanner package","Test the clean case (empty array) explicitly","Never wrap the array in an object"],"tags":["security-scanner","contract","return-type"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}