oven-sh/bun · error · Error

Security scanner must export a 'scanner' object with a versi

Error message

Security scanner must export a 'scanner' object with a version property

What it means

After a successful import, the subprocess requires a named export `scanner` that is an object with a string `version` property. This error is thrown when `import(name).scanner` is not such an object — no `scanner` export, a different export shape (default-only), or a missing/non-string `version` — and it is then reported as SCAN_FAILED with this message.

Source

Thrown at src/install/PackageManager/scanner-entry.ts:88

    }

    sendAndExit({
      type: "error",
      code: "MODULE_NOT_FOUND",
      module: scannerModuleName,
    });
  } else {
    sendAndExit({
      type: "error",
      code: "SCAN_FAILED",
      message: error instanceof Error ? error.message : String(error),
    });
  }
}

try {
  if (typeof scanner !== "object" || scanner === null || typeof scanner.version !== "string") {
    throw new Error("Security scanner must export a 'scanner' object with a version property");
  }

  if (scanner.version !== "1") {
    sendAndExit({
      type: "error",
      code: "INVALID_VERSION",
      message: `Security scanner must be version 1, got version ${scanner.version}`,
    });
  }

  if (typeof scanner.scan !== "function") {
    throw new Error(`scanner.scan is not a function, got ${typeof scanner.scan}`);
  }

  const result = await scanner.scan({ packages });

  if (!Array.isArray(result)) {
    throw new Error("Security scanner must return an array of advisories");

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Export the object as a named export: `export const scanner = { version: "1", scan }`
  2. Print the actual exports: bun -e 'import("m").then(m => console.log(Object.keys(m)))'
  3. For CJS scanners, assign module.exports.scanner statically instead of computing it
  4. Set version to the string \"1\"

Example fix

// before
export default { version: "1", scan };

// after
export const scanner = { version: "1", scan };
Defensive patterns

Strategy: type-guard

Validate before calling

const mod = await import("@corp/scanner");
if (typeof mod.scanner !== "object" || mod.scanner === null || typeof mod.scanner.version !== "string") {
  throw new Error("scanner package must export { scanner: { version: string, scan: fn } }");
}

Type guard

function isScanner(value: unknown): value is { version: string; scan: (input: { packages: unknown[] }) => Promise<unknown[]> } {
  return (
    typeof value === "object" &&
    value !== null &&
    typeof (value as { version?: unknown }).version === "string" &&
    typeof (value as { scan?: unknown }).scan === "function"
  );
}

Try / catch

try {
  if (!isScanner(mod.scanner)) throw new Error("bad scanner export shape");
} catch (e) {
  // message is the contract text; fix the scanner package
}

Prevention

When it happens

Trigger: `.scanner` is undefined (default-only export, or a CJS module whose exports are computed so the interop analysis misses them), or `scanner.version` is absent/undefined/not a string (e.g. the number 1).

Common situations: Scanner library renamed its export in a new major version; CJS scanner using `module.exports = buildScanner()` computed at load; version defined as a number; docs/examples exporting from the wrong file.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/d719d117803441aa. Report an issue: GitHub.