Under preserveModules, a default-imported JSON module is emitted with a named export for each top-level key, but those bindings are never declared, so loading the output fails at ESM link time.
Minimal repro: https://github.com/why-reproductions-are-required/rolldown-preserve-modules-json-repro
// src/index.js
import metrics from "./data.json" with { type: "json" }; // data.json: { "aBeeZee": [...], "Abel": [...] }
export function get(name) { return metrics[name]; }
Build with preserveModules: true, then import("./dist/index.js"):
SyntaxError: Export 'Abel' is not defined in module
The emitted dist/data.js differs from 1.1.2 only in the export line:
-export { data_default as default }; // 1.1.2 (works)
+export { Abel, aBeeZee, data_default as default }; // 1.1.3 (Abel/aBeeZee never declared)
Abel/aBeeZee exist only as properties of data_default, not as bindings, and aren't used by the importer (it reads the default export dynamically), yet they're emitted and break linking.
Versions: rolldown 1.1.3 (1.1.2 works) · Node v24.18.0
Likely cause: #9934 ("preserve used re-exports under preserveModules"), which emits each preserved module's full declared interface; for a JSON module the per-key "interface" has no backing bindings.
Real-world impact: breaks building cloudflare/vinext (fallback-metrics.ts default-imports fallback-metrics-data.json); consumers' vite.config.ts then crash with Export 'aBeeZee' is not defined in module.
Under
preserveModules, a default-imported JSON module is emitted with a named export for each top-level key, but those bindings are never declared, so loading the output fails at ESM link time.Minimal repro: https://github.com/why-reproductions-are-required/rolldown-preserve-modules-json-repro
Build with
preserveModules: true, thenimport("./dist/index.js"):The emitted
dist/data.jsdiffers from 1.1.2 only in the export line:Abel/aBeeZeeexist only as properties ofdata_default, not as bindings, and aren't used by the importer (it reads the default export dynamically), yet they're emitted and break linking.Versions: rolldown 1.1.3 (1.1.2 works) · Node v24.18.0
Likely cause: #9934 ("preserve used re-exports under preserveModules"), which emits each preserved module's full declared interface; for a JSON module the per-key "interface" has no backing bindings.
Real-world impact: breaks building cloudflare/vinext (
fallback-metrics.tsdefault-importsfallback-metrics-data.json); consumers'vite.config.tsthen crash withExport 'aBeeZee' is not defined in module.