{"record":{"id":"1b324688a2821d91","repo":"BoundaryML/baml","slug":"unit-source-path-is-not-root-relative-rel","errorCode":null,"errorMessage":"unit source path is not root-relative: `{rel}`","messagePattern":"unit source path is not root-relative: `(.+?)`","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml_cli/src/bytecode_cache.rs","lineNumber":1616,"sourceCode":"        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            {\n                unit_keys.insert(rel.clone(), *key);\n                continue;\n            }\n            let Some(unit) = units_by_source.get(rel.as_str()) else {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    format!(\"compiled output has no unit for `{rel}`\"),\n                ));\n            };\n            if std::path::Path::new(&unit.source_file).is_absolute() {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    format!(\"unit source path is not root-relative: `{rel}`\"),\n                ));\n            }\n            let (key, wrote) = self.cache.store_unit_shared(unit)?;\n            unit_entries_written += usize::from(wrote);\n            unit_keys.insert(rel.clone(), *key.as_bytes());\n        }\n        cache_debug(format_args!(\n            \"unit store: wrote {unit_entries_written}, reused {}\",\n            user_files.len().saturating_sub(unit_entries_written)\n        ));\n\n        let mut files: Vec<ManifestFile> = Vec::with_capacity(user_files.len());\n        for (sf, rel) in user_files {\n            // The file's assembled unit carries its emit-recorded reference\n            // edges (`CompilationUnit::referenced_names` / `bakes_type_layout`)\n            // — recorded by codegen at its resolution sites, so direct calls","sourceCodeStart":1598,"sourceCodeEnd":1634,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml_cli/src/bytecode_cache.rs#L1598-L1634","documentation":"The bytecode cache requires every unit's source_file to be a path relative to the package root, because manifest entries and cache keys are built from root-relative paths. When a unit's source_file is absolute for a file whose manifest key `rel` is relative, the two can never be reconciled, so storing is refused with InvalidData.","triggerScenarios":"store_artifacts_with_manifest finds an assembled unit via units_by_source whose unit.source_file is an absolute path (e.g. a file was registered into the compile with its absolute filesystem path instead of the path relative to the SourceRoot).","commonSituations":"A build script or harness constructs CompilationUnits from absolute paths (e.g. from an env var or absolute CLI argument) instead of paths relative to the project root; a tool running on Windows/CI passes drive-letter absolute paths into the unit list.","solutions":["Register source files with paths relative to the package/source root (strip the root prefix before constructing the unit).","Fix the caller that builds CompilationUnits to canonicalize against the project root rather than passing absolute paths.","Check custom build scripts or CI wrappers that pass absolute paths for the baml sources.","If caused by a library-internal path join, report it upstream with the platform and invocation."],"exampleFix":"// before\nCompilationUnit { source_file: \"/home/user/proj/schema.baml\", .. }\n// after\nCompilationUnit { source_file: \"schema.baml\", .. } // root-relative","handlingStrategy":"validation","validationCode":"for unit in &units {\n    if Path::new(&unit.source_file).is_absolute() {\n        return Err(format!(\"unit source must be root-relative: {}\", unit.source_file));\n    }\n}","typeGuard":"fn is_root_relative(p: &str) -> bool {\n    !std::path::Path::new(p).is_absolute()\n}","tryCatchPattern":"match store_result {\n    Err(e) if e.to_string().contains(\"not root-relative\") => {\n        eprintln!(\"fix source registration to use root-relative paths\");\n        std::process::exit(1);\n    }\n    other => other?,\n}","preventionTips":["Always construct CompilationUnit.source_file relative to the SourceRoot, never from env vars or absolute CLI args.","Strip the project-root prefix (strip_prefix) before building units.","Watch for Windows drive letters and leading '/' when porting build scripts.","Add a debug assertion in unit assembly that rejects absolute paths early."],"tags":["cache","paths","internal"],"backgroundTag":"invalid-argument-format","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"}