{"record":{"id":"0b6c783a39e462f0","repo":"a-b-street/abstreet","slug":"not-in-nodemap","errorCode":null,"errorMessage":"{:?} not in NodeMap","messagePattern":"(.+?) not in NodeMap","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/pathfind/node_map.rs","lineNumber":42,"sourceCode":"            id_to_node: Vec::new(),\n        }\n    }\n\n    pub fn get_or_insert(&mut self, node: T) -> NodeId {\n        if let Some(id) = self.node_to_id.get(&node) {\n            return *id;\n        }\n        let id = self.id_to_node.len();\n        self.node_to_id.insert(node, id);\n        self.id_to_node.push(node);\n        id\n    }\n\n    pub fn get(&self, node: T) -> NodeId {\n        if let Some(id) = self.node_to_id.get(&node) {\n            *id\n        } else {\n            panic!(\"{:?} not in NodeMap\", node);\n        }\n    }\n\n    pub fn translate_id(&self, id: usize) -> T {\n        self.id_to_node[id]\n    }\n\n    /// Call this after filling out the input graph, right before preparation.\n    pub fn guarantee_node_ordering(&self, input_graph: &mut InputGraph) {\n        // The fast_paths implementation will trim out the last nodes in the input graph if there\n        // are no edges involving them:\n        // https://github.com/easbar/fast_paths/blob/fdb65f25c5485c9c74c1b3cbe66d829eea81b14b/src/input_graph.rs#L151\n        //\n        // We sometimes add nodes that aren't used yet, so that we can reuse the same node ordering\n        // later. Detect if the last node isn't used.\n        let last_node = self.id_to_node.len() - 1;\n        input_graph.freeze();\n        for edge in input_graph.get_edges() {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/pathfind/node_map.rs#L24-L60","documentation":"NodeMap::get looks up the NodeId for a node of generic type T; if the node was never inserted into the map, it panics with \"{:?} not in NodeMap\". The library treats a missing node as a programmer error rather than a recoverable condition, since callers are expected to have inserted every node they later query.","triggerScenarios":"Calling get(node) with a node that was never added to the NodeMap, or calling get on a node from a different NodeMap instance; also via translate_id misuse indirectly after stale indexing.","commonSituations":"Building a graph where some nodes were skipped during insertion but later referenced during edge/path construction; reusing node keys across maps; typos or case differences in node identifiers.","solutions":["Ensure every node is inserted into the NodeMap (via insert_or_ignore) before calling get","Use entry or a get_or_insert-style API so the node is added on first reference","Use the non-panicking lookup (node_to_id.get) and handle the None case yourself","Verify you are querying the same NodeMap instance the node was registered in"],"exampleFix":"// before\nlet id = node_map.get(node);\n// after\nlet id = match node_map.node_to_id.get(&node) {\n    Some(id) => *id,\n    None => { node_map.insert_or_ignore(node.clone()); node_map.get(node) }\n};","handlingStrategy":"validation","validationCode":"if node_map.node_to_id.contains_key(&node) { let id = node_map.get(node); } else { /* insert or handle missing */ }","typeGuard":"fn lookup<T: Clone + std::hash::Hash + Eq>(map: &NodeMap<T>, node: &T) -> Option<NodeId> {\n    map.node_to_id.get(node).copied()\n}","tryCatchPattern":"// panics are not catchable in Rust; guard before calling:\nlet id = node_map.node_to_id.get(&node).copied()\n    .unwrap_or_else(|| panic_once_with_context(node));","preventionTips":["Insert every node before querying; never assume nodes exist","Prefer insert_or_ignore or entry-based insertion at first reference","Ensure only one NodeMap instance is used per graph build","Log/collect missing nodes instead of failing on the first one"],"tags":["rust","panic","lookup-failed","graph"],"backgroundTag":"entity-not-found","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}