{"record":{"id":"ab5d580b08be3380","repo":"BoundaryML/baml","slug":"duplicate-compilation-unit-for","errorCode":null,"errorMessage":"duplicate compilation unit for `{}`","messagePattern":"duplicate compilation unit for `(.+?)`","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml_cli/src/bytecode_cache.rs","lineNumber":1587,"sourceCode":"            CompiledUnits::Fresh(units) => (units, false),\n            CompiledUnits::Reused(units) => (units, true),\n            CompiledUnits::None => {\n                debug_assert!(false, \"cached compile stored without assembled units\");\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    \"compile produced no assembled units\",\n                ));\n            }\n        };\n        self.store(&compiled.program)?;\n\n        let mut units_by_source = HashMap::with_capacity(units.len());\n        for unit in units {\n            if units_by_source\n                .insert(unit.source_file.as_str(), unit)\n                .is_some()\n            {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    format!(\"duplicate compilation unit for `{}`\", unit.source_file),\n                ));\n            }\n        }\n\n        let user_files = user_files_with_rel_paths(db, package);\n        // Only a successful reuse compile returns assembled `units`. A full\n        // fallback must persist freshly decomposed units for every file rather\n        // than carrying pointers from the abandoned reuse plan.\n        let pointer_plan = if reused_units { plan } else { None };\n        let mut unit_keys = HashMap::with_capacity(user_files.len());\n        let mut unit_entries_written = 0usize;\n        for (_, rel) in &user_files {\n            if let Some(key) = pointer_plan\n                .filter(|plan| plan.clean_files.contains(rel))\n                .and_then(|plan| plan.unit_keys.get(rel))\n            {","sourceCodeStart":1569,"sourceCodeEnd":1605,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml_cli/src/bytecode_cache.rs#L1569-L1605","documentation":"baml_cli's bytecode cache refuses to store artifacts when the compile produced two CompilationUnits with the same source_file. The units map is keyed by root-relative source path so each current project file maps to exactly one unit; a collision means the compiler assembled its unit list inconsistently, which is a programmer/internal invariant error rather than something user input normally causes.","triggerScenarios":"store_artifacts_with_manifest (via verify_and_store) receives a CompiledArtifacts whose units slice contains two entries with identical unit.source_file strings — e.g. the same .baml file was added to the unit list twice during assembly (duplicated user_files entry, symlink/alias resolving to one file under two names, or a bug in the unit-collection pass).","commonSituations":"A file referenced through two different paths that normalize to the same source_file; a plugin/generator or test harness feeding the same file to the compile twice; a corrupt or hand-edited cache state being replayed; a compiler bug in unit assembly after recent changes to how files are enumerated.","solutions":["Identify the duplicated source path in the message and remove one of the two ways it enters the build (duplicate include, symlink alias, double registration).","Run a clean rebuild: delete the baml cache directory and recompile so no stale/reused units are carried in.","If it reproduces on a clean tree, report it upstream with the project layout — this is an internal invariant violation in unit assembly.","Check for symlinks or case-insensitive-filesystem aliases that make one file reachable under two paths and normalize them."],"exampleFix":"// before: same file registered twice\ncompile(&[\"schema.baml\", \"./schema.baml\"])\n// after: deduplicate paths before compiling\nlet files: BTreeSet<PathBuf> = [\"schema.bml\".into(), \"./schema.baml\".into()].into_iter().collect();","handlingStrategy":"validation","validationCode":"let mut seen = std::collections::HashSet::new();\nfor f in &input_files {\n    let canonical = f.canonicalize()?;\n    if !seen.insert(canonical) {\n        return Err(format!(\"duplicate source file: {}\", f.display()));\n    }\n}","typeGuard":"fn all_paths_unique(files: &[PathBuf]) -> bool {\n    let canon: Vec<_> = files.iter().filter_map(|f| f.canonicalize().ok()).collect();\n    canon.len() == canon.iter().collect::<std::collections::HashSet<_>>().len()\n}","tryCatchPattern":null,"preventionTips":["Canonicalize paths before registering sources so symlinks/aliases collapse to one entry.","Deduplicate the file list (BTreeSet/HashSet) before invoking the compiler.","Avoid feeding the same file via include globs and explicit lists simultaneously.","Report occurrences on a clean tree upstream — this signals an internal bug, not user error."],"tags":["cache","internal","compiler"],"backgroundTag":"internal-invariant-violation","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}