{"record":{"id":"c70b92613a38e2e9","repo":"a-b-street/abstreet","slug":"number-of-lanes-in-is-fwd-back-now-but-in-the-edits","errorCode":null,"errorMessage":"number of lanes in {} is ({} fwd, {} back) now, but ({}, {}) in the edits","messagePattern":"number of lanes in (.+?) is \\((.+?) fwd, (.+?) back\\) now, but \\((.+?), (.+?)\\) in the edits","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/edits/compat.rs","lineNumber":518,"sourceCode":"struct ChangeSpeedLimit {\n    id: OriginalRoad,\n    new: Speed,\n    old: Speed,\n}\n#[derive(Debug, Deserialize)]\nstruct ChangeAccessRestrictions {\n    id: OriginalRoad,\n    new: AccessRestrictions,\n    old: AccessRestrictions,\n}\n\nimpl OriginalLane {\n    fn lookup(&self, map: &Map) -> Result<(RoadID, usize)> {\n        let r = map.get_r(map.find_r_by_osm_id(self.parent)?);\n        let current_fwd = r.children_forwards();\n        let current_back = r.children_backwards();\n        if current_fwd.len() != self.num_fwd || current_back.len() != self.num_back {\n            bail!(\n                \"number of lanes in {} is ({} fwd, {} back) now, but ({}, {}) in the edits\",\n                r.orig_id,\n                current_fwd.len(),\n                current_back.len(),\n                self.num_fwd,\n                self.num_back\n            );\n        }\n        let l = if self.dir == Direction::Fwd {\n            current_fwd[self.idx].0\n        } else {\n            current_back[self.idx].0\n        };\n        Ok((r.id, l.offset))\n    }\n}\n","sourceCodeStart":500,"sourceCodeEnd":535,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/edits/compat.rs#L500-L535","documentation":"OriginalLane::lookup resolves a lane reference saved in an old edit by OSM road ID plus the recorded counts of forward/backward lanes. If the current road's actual lane counts differ from the edit's snapshot, the lane can no longer be identified unambiguously, so lookup fails.","triggerScenarios":"Upgrading/loading edits that reference lanes whose parent road now has a different number of fwd/back lanes (current children_forwards/backwards lengths != num_fwd/num_back), typically after map regeneration from changed OSM data.","commonSituations":"OSM edits added/removed lanes on a road; loading edits from an older map build; lane counts changed by prior edits baked into the basemap.","solutions":["Regenerate the map from the OSM snapshot the edits were created against.","Update the edit file's num_fwd/num_back values to match the current lane counts.","Remove commands referencing the changed road and re-create them in the app."],"exampleFix":"// before (edit JSON)\n{\"parent\": 17, \"num_fwd\": 2, \"num_back\": 1, \"idx\": 0}\n// after: match current map (3 fwd, 1 back)\n{\"parent\": 17, \"num_fwd\": 3, \"num_back\": 1, \"idx\": 0}","handlingStrategy":"validation","validationCode":"// check lane counts on the parent road before resolving the lane\nlet r = map.get_r(map.find_r_by_osm_id(orig.parent)?);\nlet ok = r.children_forwards().len() == orig.num_fwd\n    && r.children_backwards().len() == orig.num_back;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check OSM lane-count diffs before reusing old edit files.","Update num_fwd/num_back in edits when lanes change upstream.","Pin edits to the OSM snapshot they were authored against."],"tags":["edits","lane-count","state-mismatch"],"backgroundTag":"schema-validation-failed","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"}