{"id":"feb8169af6d01b59","repo":"rust-lang/rust","slug":"cannot-decode-attrid-with-cachedecoder","errorCode":null,"errorMessage":"cannot decode `AttrId` with `CacheDecoder`","messagePattern":"cannot decode `AttrId` with `CacheDecoder`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_middle/src/query/on_disk_cache.rs","lineNumber":667,"sourceCode":"    // compilation sessions. We use the `DefPathHash`, which is stable across\n    // sessions, to map the old `DefId` to the new one.\n    fn decode_def_id(&mut self) -> DefId {\n        // Load the `DefPathHash` which is was we encoded the `DefId` as.\n        let def_path_hash = DefPathHash::decode(self);\n\n        // Using the `DefPathHash`, we can lookup the new `DefId`.\n        // Subtle: We only encode a `DefId` as part of a query result.\n        // If we get to this point, then all of the query inputs were green,\n        // which means that the definition with this hash is guaranteed to\n        // still exist in the current compilation session.\n        match self.tcx.def_path_hash_to_def_id(def_path_hash) {\n            Some(r) => r,\n            None => panic!(\"Failed to convert DefPathHash {def_path_hash:?}\"),\n        }\n    }\n\n    fn decode_attr_id(&mut self) -> rustc_span::AttrId {\n        panic!(\"cannot decode `AttrId` with `CacheDecoder`\");\n    }\n}\n\nimpl<'a, 'tcx> BlobDecoder for CacheDecoder<'a, 'tcx> {\n    fn decode_symbol(&mut self) -> Symbol {\n        self.decode_symbol_or_byte_symbol(\n            Symbol::new,\n            |this| Symbol::intern(this.read_str()),\n            |opaque| Symbol::intern(opaque.read_str()),\n        )\n    }\n\n    fn decode_byte_symbol(&mut self) -> ByteSymbol {\n        self.decode_symbol_or_byte_symbol(\n            ByteSymbol::new,\n            |this| ByteSymbol::intern(this.read_byte_str()),\n            |opaque| ByteSymbol::intern(opaque.read_byte_str()),\n        )","sourceCodeStart":649,"sourceCodeEnd":685,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_middle/src/query/on_disk_cache.rs#L649-L685","documentation":"`CacheDecoder::decode_attr_id` (on_disk_cache.rs:667) is intentionally a hard `panic!(\"cannot decode AttrId with CacheDecoder\")`. `AttrId` is an interner key whose numeric value is not stable across compilation sessions, so it cannot be safely restored from the incremental on-disk cache. The decoder refuses rather than silently returning a wrong attribute. Hitting it means some type that (directly or transitively) contains an `AttrId` was encoded into a cross-session query result, which is a compiler bug.","triggerScenarios":"Reached when `Decodable<CacheDecoder>` is derived or hand-written for a struct/enum that contains an `AttrId` (or a field whose type contains one), and a query returning that type gets persisted to disk via the incremental cache. The derive blindly generates a call to `decode_attr_id`, which always panics.","commonSituations":"Seen by rustc contributors extending the query system or adding a new persisted type that inadvertently includes HIR attribute data, or by tooling that derives `Decodable` for a wrapper around an `AttrId`-bearing type and persists it. End users of stable rustc do not trigger this; if a stable build hits it, the compiler itself regressed.","solutions":["Report to rust-lang/rust; this indicates an `AttrId`-bearing type was persisted cross-session, which is unsupported.","If you added the offending type in-tree, exclude it from cross-session caching or convert the `AttrId` to a stable form (e.g. re-encode the attribute's logical content, not the interner key) before persisting.","Audit the new `Decodable<CacheDecoder>` impl: grep the type's fields for `AttrId` / `Attribute` and remove or re-map them.","Re-run `x.py test compiler/rustc_middle` after the change to confirm no query result re-introduces the path."],"exampleFix":"// before — derive blindly persists an unstable interner key\n#[derive(Encodable, Decodable)]\nstruct PersistedItem {\n    attrs: Vec<rustc_ast::AttrId>, // panics on decode\n    body: BodyId,\n}\n\n// after — store a stable representation instead\n#[derive(Encodable, Decodable)]\nstruct PersistedItem {\n    attr_kinds: Vec<AttrKind>, // logical, session-stable content\n    body: BodyId,\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// AttrId decoding with CacheDecoder fails when the cache predates a serialization\n// format change (typical after a rustc update). No source guard exists.\nuse std::process::Command;\nfn build_after_toolchain_bump(dir: &str) -> std::io::Result<std::process::ExitStatus> {\n    // Wipe artifacts encoded by the previous rustc before rebuilding.\n    let _ = Command::new(\"cargo\").args([\"clean\"]).current_dir(dir).status();\n    Command::new(\"cargo\").arg(\"build\").current_dir(dir).status()\n}","preventionTips":["Always `cargo clean` (or at least remove `target/<profile>/incremental`) after a rustup update.","Do not cache `target/` keyed only on branch; include rustc version in the cache key.","Prefer stable for shared build environments; nightly serialization formats churn.","If reproducible on current nightly, file an ICE — AttrId format should be versioned."],"tags":["rustc","incremental-compilation","on-disk-cache","attrid","serialization","internal-compiler-error"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}