oven-sh/bun · error · Error
bad
Error message
bad
What it means
Stress test of Bun's module.exports handling in CommonJS. This particular throw lives inside a setter deliberately installed via Object.defineProperty(module, 'exports', { get() { return 42; }, set() { throw new Error('bad'); } }). Its purpose is to prove that defining — and later reading — module.exports never performs a plain assignment through the property. The error fires only if the runtime actually invokes the setter, i.e. something assigned to module.exports and triggered the user-visible [[Set]] instead of defining the property.
Source
Thrown at bench/snippets/module-exports-putter.cjs:10
// This is a stress test of some internals in How Bun does the module.exports assignment.
// If it crashes or throws then this fails
import("../runner.mjs").then(({ bench, run }) => {
bench("Object.defineProperty(module, 'exports', { get() { return 42; } })", () => {
Object.defineProperty(module, "exports", {
get() {
return 42;
},
set() {
throw new Error("bad");
},
configurable: true,
});
if (module.exports !== 42) throw new Error("bad");
if (!Object.getOwnPropertyDescriptor(module, "exports").get) throw new Error("bad");
});
bench("Object.defineProperty(module.exports = {})", () => {
Object.defineProperty(module, "exports", {
value: { abc: 123 },
});
if (!module.exports.abc) throw new Error("bad");
if (Object.getOwnPropertyDescriptor(module, "exports").value !== module.exports) throw new Error("bad");
});
bench("module.exports = {}", () => {
module.exports = { abc: 123 };View on GitHub (pinned to 8c5296ac45)
Solutions
- Minimize to a single .cjs file: install the accessor, then only read module.exports and the descriptor; if it throws, the runtime invoked the setter
- Run the same file under Node to confirm the expected (non-throwing) behavior
- If Bun-only, report to oven-sh/bun with the minimized file — the module.exports define path is doing an assignment
Defensive patterns
Strategy: validation
Validate before calling
// prove the setter is never invoked when defining/reading module.exports
let setterCalled = false;
Object.defineProperty(module, 'exports', {
get() { return 42; },
set() { setterCalled = true; },
configurable: true,
});
void module.exports;
if (setterCalled) throw new Error('runtime invoked the module.exports setter during define/read'); Prevention
- In application code, prefer plain `module.exports = value` — accessor tricks on module.exports are edge-case territory even on Node
- Add conformance tests that define poisoned setters on module.exports when changing CJS wrapper code in Bun
- Compare any exotic module.exports behavior against Node first to know which runtime is wrong
When it happens
Trigger: Object.defineProperty on `module` with an accessor pair whose setter throws, followed by any code path (module wrapper, transpiled output, engine internals) that does `module.exports = value` instead of Object.defineProperty — the assignment calls the poisoned setter.
Common situations: Regressions in Bun's CJS module wrapper / exports putter that fall back to assignment; transpilers or bundlers emitting `module.exports = ...` after user code installs an accessor; comparing Bun against Node where Node never calls the setter during defineProperty.
Related errors
- Second buffer was modified
- Third buffer was modified
- bad result
- Expected ${expected} to be ${equal} for ${description}
- Please run `make compile-ffi-test` to compile the ffi test l
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/9e126f2b719e3852.
Report an issue: GitHub.