{"record":{"id":"14bb82b437f2fb8f","repo":"BoundaryML/baml","slug":"baml-cache-verify-cached-interface-fragment-for-differs-from","errorCode":null,"errorMessage":"BAML_CACHE_VERIFY: cached interface fragment for `{}` differs from a fresh derivation ({} cached vs {} fresh bytes). A clean file's stored fragment is a stale substitute — the throws-taint closure failed to dirty a file whose `callable_throws` changed, so the seeded value would be wrong. Please report this.","messagePattern":"BAML_CACHE_VERIFY: cached interface fragment for `(.+?)` differs from a fresh derivation \\((.+?) cached vs (.+?) fresh bytes\\)\\. A clean file's stored fragment is a stale substitute — the throws-taint closure failed to dirty a file whose `callable_throws` changed, so the seeded value would be wrong\\. Please report this\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml_cli/src/bytecode_cache.rs","lineNumber":2053,"sourceCode":"            if !clean_files.contains(&entry.rel_path) || entry.callable_throws_fragment.is_empty() {\n                continue;\n            }\n            let full = root.join(&entry.rel_path);\n            let Some(sf) = db.get_file(&full) else {\n                continue; // file removed — never seeded\n            };\n            let honest =\n                baml_db::baml_compiler2_hir_ty::package_interface::export_callable_throws_fragment(\n                    db, sf,\n                );\n            let honest_bytes = borsh::to_vec(&honest).map_err(|e| {\n                anyhow::anyhow!(\n                    \"honest interface fragment for `{}` failed to serialize: {e}\",\n                    entry.rel_path\n                )\n            })?;\n            if honest_bytes != entry.callable_throws_fragment {\n                anyhow::bail!(\n                    \"BAML_CACHE_VERIFY: cached interface fragment for `{}` differs from a fresh \\\n                     derivation ({} cached vs {} fresh bytes). A clean file's stored fragment is \\\n                     a stale substitute — the throws-taint closure failed to dirty a file whose \\\n                     `callable_throws` changed, so the seeded value would be \\\n                     wrong. Please report this.\",\n                    entry.rel_path,\n                    entry.callable_throws_fragment.len(),\n                    honest_bytes.len(),\n                );\n            }\n        }\n        Ok(())\n    }\n\n    /// The `BAML_CACHE_SAMPLED_VERIFY` knob: `Some(false)` disables sampling,\n    /// `Some(true)` forces it on every warm compile (tests want determinism),\n    /// `None` leaves the default 1/32 gate. Any other value is treated as unset.\n    fn sampled_verify_force() -> Option<bool> {","sourceCodeStart":2035,"sourceCodeEnd":2071,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml_cli/src/bytecode_cache.rs#L2035-L2071","documentation":"BAML_CACHE_VERIFY compares a cached file's stored callable_throws_fragment against a freshly derived one. When the bytes differ, the incremental cache's dirtying logic (throws-taint closure) failed to mark the file stale after its callable_throws changed, so the cached value is wrong and a warm build would produce incorrect results. This is explicitly an internal cache-soundness bug the maintainers ask be reported.","triggerScenarios":"Building with BAML_CACHE_VERIFY=1 where a file is considered 'clean' in the incremental plan but its re-derived export_callable_throws_fragment bytes differ from entry.callable_throws_fragment — i.e. throws propagation changed without the file being dirtied.","commonSituations":"Editing a function's `throws` clause (or a callee's) in one file and relying on a warm build; compiler upgrades that changed throws-taint rules while old cache entries persist; multi-file dependency graphs where taint closure misses a dependent file.","solutions":["Delete the incremental bytecode cache (`.baml` / profiles-v1 sibling cache) and rebuild clean.","Re-run with BAML_CACHE_VERIFY=1 after a clean build to confirm the fresh cache verifies.","Report the reproduction to the baml maintainers — the taint closure missing a dirty is a compiler bug."],"exampleFix":"# before\nbaml build  # warm cache, possibly stale throws\n# after\nrm -rf .baml && BAML_CACHE_VERIFY=1 baml build","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = build() {\n    if e.to_string().contains(\"BAML_CACHE_VERIFY\") {\n        fs::remove_dir_all(\".baml\"); // discard unsound cache, rebuild clean\n    }\n}","preventionTips":["Wipe the cache after editing throws clauses in dependency files","Run a clean build in CI rather than restoring warm caches across branches","Run BAML_CACHE_VERIFY=1 occasionally on warm builds to catch stale seeds early"],"tags":["cache","incremental-compilation","cache-soundness","rust"],"backgroundTag":"checksum-mismatch","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"}