{"record":{"id":"4ae78e02915dea9c","repo":"swc-project/swc","slug":"multiple-identifiers-equivalent-up-to-span-hygiene","errorCode":null,"errorMessage":"Multiple identifiers equivalent up to span hygiene found: {:#?}\\nFirst = {:#?}\\nSecond = {:#?}","messagePattern":"Multiple identifiers equivalent up to span hygiene found: (.+?)\\\\nFirst = (.+?)\\\\nSecond = (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_bundler/src/inline.rs","lineNumber":51,"sourceCode":"    module.par_visit_mut_with(&mut v);\n    module.retain_mut(|_, s| !matches!(s, ModuleItem::Stmt(Stmt::Empty(..))));\n}\n\n#[derive(Debug)]\n#[cfg_attr(feature = \"concurrent\", derive(Clone))]\nstruct Inliner {\n    data: Readonly<InlineData>,\n}\n\nstruct Analyzer<'a> {\n    injected_ctxt: SyntaxContext,\n    data: &'a mut InlineData,\n}\n\nimpl Analyzer<'_> {\n    fn store(&mut self, from: Id, to: Id) {\n        if let Some(prev) = self.data.ids.insert(from.clone(), to.clone()) {\n            unreachable!(\n                \"Multiple identifiers equivalent up to span hygiene found: {:#?}\\nFirst = \\\n                 {:#?}\\nSecond = {:#?}\",\n                from, prev, to\n            )\n        }\n    }\n}\n\nimpl Visit for Analyzer<'_> {\n    noop_visit_type!();\n\n    /// Noop\n    fn visit_module_decl(&mut self, _: &ModuleDecl) {}\n\n    /// Noop. We don't inline variables declared in subscopes.\n    fn visit_function(&mut self, _: &Function) {}\n\n    /// Noop. We don't inline variables declared in subscopes.","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_bundler/src/inline.rs#L33-L69","documentation":"swc_bundler's inliner builds equivalence classes of identifiers that are identical up to span hygiene (symbol + SyntaxContext). store() panics if the same Id is inserted twice with different targets, meaning analysis found two bindings it considers the same identifier that must inline to different places — an invariant break almost always caused by hygiene marks being lost, reused, or duplicated by earlier transforms.","triggerScenarios":"Bundling with the inlining step enabled where two modules (or two transforms of the same module) produce bindings with identical symbol and SyntaxContext that inline differently; custom passes that clone AST nodes without assigning fresh marks; reusing one Globals/Mark context across sequential builds in the same process.","commonSituations":"Custom swc transforms executed before bundling that clone/copy bindings; long-lived build servers that reuse swc_common::Globals between compilations; heavy macro- or codemod-generated code entering the graph.","solutions":["Create fresh Globals (swc_common::globals::Globals::new()) for every compilation so SyntaxContexts never repeat","Audit custom passes for node cloning that duplicates identifiers without fresh hygiene marks (use Mark/resolver correctly)","Confirm the inliner is the trigger by disabling inlining; if so, reduce the two colliding modules and report upstream"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| bundler.bundle(&entries)?));\nmatch out {\n    Ok(v) => v,\n    Err(p) if panic_message(&p).contains(\"span hygiene\") => {\n        // fallback: rerun the whole build with fresh Globals and inlining disabled\n        swc_common::globals::Globals::new().set(|| { /* rebuild without inline */ });\n    }\n    Err(p) => std::panic::resume_unwind(p),\n}","preventionTips":["Create fresh swc_common::Globals (and Marks) per compilation, never share them across builds","Audit custom transforms for AST cloning that duplicates identifiers without fresh hygiene marks","Provide a build option to disable bundler inlining so there is always a fallback path","Run the bundler in a worker process to contain hygiene panics"],"tags":["swc","bundler","hygiene","identifier","inlining"],"backgroundTag":"identifier-hygiene-collision","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}