swc-project/swc · error
Plan does not contain bundle kind for {:?}
Error message
Plan does not contain bundle kind for {:?} What it means
After merging modules into bundles, swc_bundler looks each bundle's entry id up in the ChunkPlan (plan.entries) to recover its BundleKind. The plan and the merged-entry list are derived from the same module graph, so a missing id means the two data structures disagree — an internal chunk-planning invariant violation (this copy of the code is the non-inlining branch of the two).
Source
Thrown at crates/swc_bundler/src/bundler/chunk/mod.rs:110
.collect::<Vec<_>>();
let merged: Vec<_> = if entries.len() == 1 {
entries
.into_iter()
.map(|(id, mut entry)| {
self.merge_into_entry(&ctx, id, &mut entry, &mut all);
#[cfg(debug_assertions)]
tracing::debug!("Merged `{}` and it's dep into an entry", id);
(id, entry)
})
.map(|(id, module)| {
let kind = plan
.entries
.get(&id)
.unwrap_or_else(|| {
unreachable!("Plan does not contain bundle kind for {:?}", id)
})
.clone();
Bundle {
kind,
id,
module: module.into(),
}
})
.collect()
} else {
entries
.into_iter()
.map(|(id, mut entry)| {
let mut a = all.clone();
self.merge_into_entry(&ctx, id, &mut entry, &mut a);
#[cfg(debug_assertions)]
tracing::debug!("Merged `{}` and it's dep into an entry", id);View on GitHub (pinned to 5176682b65)
Solutions
- Update the whole swc workspace to a single version so chunk planning and merging run the same code
- If you implement Load/Resolve/ModuleRecord, guarantee one stable id per resolved module (return the same id for the same path every time)
- Simplify the entry list until the panic disappears to identify the conflicting entry, then report the reduced graph to swc
Defensive patterns
Strategy: fallback
Validate before calling
// Before bundling, assert every entry id is present in the module graph you feed in
fn entries_known(entries: &[ModuleId], graph: &FxHashSet<ModuleId>) -> Result<(), String> {
for e in entries {
if !graph.contains(e) {
return Err(format!("entry {:?} missing from module graph", e));
}
}
Ok(())
} Try / catch
let modules = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
bundler.bundle(&entries)?
}));
if modules.is_err() {
// fall back: bundle each entry separately (single-entry bundles avoid the merge/planning path)
for e in &entries { let _ = bundler.bundle(std::iter::once(e).collect())?; }
} Prevention
- Keep all swc crates version-aligned
- Make custom loaders return the same id for the same resolved path on every call
- Avoid passing the same module as both entry and dependency of another entry
- Wrap bundling in catch_unwind or a subprocess so panics degrade to a build error, not a crash
When it happens
Trigger: Running bundle generation where module ids differ between chunk planning and merging: custom loaders returning fresh ids per call (e.g. allocating a new Atom each load), virtual modules whose id is not stable across phases, or graphs where entry deduplication behaves differently in the plan vs the merge step.
Common situations: Custom ModuleRecord-building plugins or virtual-module loaders; bundling many entries that share dependencies; partial upgrades that leave swc_bundler and its sibling crates on mismatched versions.
Related errors
- {id:?} should not be wrapped with a function
- Modules reexported with `export * as foo from './foo'` shoul
- Decl in ExportDecl: {:?}
- internal error: entered unreachable code
- Non-computed member expression with property other than iden
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/112da83bb7142d3d.
Report an issue: GitHub.