{"record":{"id":"9b6451f6bede8499","repo":"oven-sh/bun","slug":"scanner-scan-is-not-a-function-got-typeof-scann","errorCode":null,"errorMessage":"scanner.scan is not a function, got ${typeof scanner.scan}","messagePattern":"scanner\\.scan is not a function, got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/install/PackageManager/scanner-entry.ts","lineNumber":100,"sourceCode":"    });\n  }\n}\n\ntry {\n  if (typeof scanner !== \"object\" || scanner === null || typeof scanner.version !== \"string\") {\n    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\",","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/install/PackageManager/scanner-entry.ts#L82-L118","documentation":"The imported scanner object passed the shape and version checks, but `typeof scanner.scan !== \"function\"`. The thrown message includes the actual type (\"scanner.scan is not a function, got undefined\") and is reported as SCAN_FAILED.","triggerScenarios":"The method is named scanPackages/run/audit instead of scan; scan exists on the default export but not on the named `scanner` object; scan is defined as a non-function property (string, boolean, object).","commonSituations":"API renamed in a scanner update; partial refactor leaving scan on a nested object; implementation copied from a different scanner version's docs.","solutions":["Name the method exactly `scan` on the exported scanner object","Inspect what actually shipped: bun -e 'import(\"m\").then(m => console.log(typeof m.scanner.scan))'","Pin the scanner version whose contract you implemented"],"exampleFix":"// before\nexport const scanner = { version: \"1\", scanPackages: async ({ packages }) => [] };\n\n// after\nexport const scanner = { version: \"1\", scan: async ({ packages }) => [] };","handlingStrategy":"type-guard","validationCode":"const { scanner } = await import(\"@corp/scanner\");\nif (typeof scanner.scan !== \"function\") {\n  throw new Error(`scanner.scan is ${typeof scanner.scan}; expected a function`);\n}","typeGuard":"function hasScan(s: unknown): s is { scan: (input: { packages: unknown[] }) => Promise<unknown[]> } {\n  return typeof (s as { scan?: unknown })?.scan === \"function\";\n}","tryCatchPattern":null,"preventionTips":["Contract-test the full shape (version + scan) in one unit test","Keep a reference scanner implementation to diff against","Pin the scanner version whose contract you coded to"],"tags":["security-scanner","contract","api-shape"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}