{"record":{"id":"8f120ce24badaf0e","repo":"rust-lang/rust-analyzer","slug":"can-t-find-ast-id-in-astidmap","errorCode":null,"errorMessage":"Can't find ast id {:?} in AstIdMap:\n{:?}","messagePattern":"Can't find ast id (.+?) in AstIdMap:\n(.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/span/src/ast_id.rs","lineNumber":852,"sourceCode":"        let hash = hash_ptr(&ptr);\n        let idx = *self.ptr_map.find(hash, |&idx| self.arena[idx].0 == ptr)?;\n        Some(self.arena[idx].1)\n    }\n\n    // Don't bound on `AstIdNode` here, because `BlockExpr`s are also valid here (`ast::BlockExpr`\n    // doesn't always have a matching `FileAstId`, but a `FileAstId<ast::BlockExpr>` always has\n    // a matching node).\n    pub fn get<N: AstNode>(&self, id: FileAstId<N>) -> AstPtr<N> {\n        let ptr = self.get_erased(id.raw);\n        AstPtr::try_from_raw(ptr)\n            .unwrap_or_else(|| panic!(\"AstIdMap node mismatch with node `{ptr:?}`\"))\n    }\n\n    pub fn get_erased(&self, id: ErasedFileAstId) -> SyntaxNodePtr {\n        let hash = hash_ast_id(&id);\n        match self.id_map.find(hash, |&idx| self.arena[idx].1 == id) {\n            Some(&idx) => self.arena[idx].0,\n            None => panic!(\n                \"Can't find ast id {:?} in AstIdMap:\\n{:?}\",\n                id,\n                self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),\n            ),\n        }\n    }\n}\n\n#[cfg(not(no_salsa_async_drops))]\nimpl Drop for AstIdMap {\n    fn drop(&mut self) {\n        let arena = std::mem::take(&mut self.arena);\n        let ptr_map = std::mem::take(&mut self.ptr_map);\n        let id_map = std::mem::take(&mut self.id_map);\n        static AST_ID_MAP_DROP_THREAD: std::sync::OnceLock<\n            std::sync::mpsc::Sender<(\n                Arena<(SyntaxNodePtr, ErasedFileAstId)>,\n                hashbrown::HashTable<ArenaId>,","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/span/src/ast_id.rs#L834-L870","documentation":"`AstIdMap::get_erased` looks up an ErasedFileAstId in the map's open-addressed hash table and panics when the id is absent. Every valid id must have been produced by this same map, so a miss means the id is stale (map was rebuilt after a file edit) or foreign (from another file/map). The panic dumps the id and all mapped entries to aid debugging.","triggerScenarios":"Looking up a FileAstId/ErasedFileAstId after the file changed and the AstIdMap was recomputed; using an id obtained from a different file's AstIdMap; decoding an id from raw bits incorrectly and querying it directly via `get_erased`.","commonSituations":"Salsa queries caching ids across revisions while the underlying file changed (edits, saves by formatter); name-resolution or completion code holding ids across an inconsistent input snapshot; tests constructing ids by hand.","solutions":["Re-resolve the id from the current file's AstIdMap (query the fresh AstIdMap salsa input) instead of reusing a cached id","Ensure ids are never stored/compared across different files or salsa revisions","If persisting ids, validate the map revision before lookup and fall back to re-resolution on miss"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check the id resolves before using it (staleness guard):\nif !map.contains(id.erased()) {\n    id = recompute_file_ast_id(current_parse, symbol_key)?; // re-derive from current revision\n}","typeGuard":null,"tryCatchPattern":"let ptr = std::panic::catch_unwind(AssertUnwindSafe(|| map.get_erased(id)))\n    .ok()\n    .or_else(|| recompute_and_lookup(id))?;","preventionTips":["Treat FileAstId as revision-scoped: re-query the AstIdMap after any file change","Never persist ids across saves or across files","Use semantic keys (names/paths) plus fresh id resolution instead of long-lived raw ids"],"tags":["rust","panic","stale-data","salsa","ast"],"backgroundTag":"stale-ast-id-map","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}