{"record":{"id":"102ccd821cddf1ae","repo":"a-b-street/abstreet","slug":"number-of-lanes-in-is-now-but-in-the-edits","errorCode":null,"errorMessage":"number of lanes in {} is {} now, but {} in the edits","messagePattern":"number of lanes in (.+?) is (.+?) now, but (.+?) in the edits","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/edits/perma.rs","lineNumber":121,"sourceCode":"impl PermanentEditCmd {\n    pub fn into_cmd(self, map: &Map) -> Result<EditCmd> {\n        match self {\n            PermanentEditCmd::ChangeRoad { r, new, old } => {\n                let id = map.find_r_by_osm_id(r)?;\n                let num_current = map.get_r(id).lanes.len();\n                // The basemap changed -- it'd be pretty hard to understand the original\n                // intent of the edit.\n                if num_current != old.lanes_ltr.len() {\n                    if IGNORE_OLD_LANES {\n                        warn!(\"Lanes in {r} have changed since the edits, but keeping the edits anyway\");\n                        return Ok(EditCmd::ChangeRoad {\n                            r: id,\n                            new,\n                            // Note we change 'old' to match the current basemap\n                            old: EditRoad::get_orig_from_osm(map.get_r(id), map.get_config()),\n                        });\n                    } else {\n                        bail!(\n                            \"number of lanes in {} is {} now, but {} in the edits\",\n                            r,\n                            num_current,\n                            old.lanes_ltr.len()\n                        );\n                    }\n                }\n                Ok(EditCmd::ChangeRoad { r: id, new, old })\n            }\n            PermanentEditCmd::ChangeIntersection { i, new, old } => {\n                let id = map.find_i_by_osm_id(i)?;\n                Ok(EditCmd::ChangeIntersection {\n                    i: id,\n                    new: new\n                        .with_permanent(id, map)\n                        .with_context(|| format!(\"new ChangeIntersection of {} invalid\", i))?,\n                    old: old\n                        .with_permanent(id, map)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/edits/perma.rs#L103-L139","documentation":"PermaEdits::into_cmd converts a persisted road edit into a command by comparing the edited lane list against the road's current lanes. If the road now has a different total number of lanes than the saved edit's lanes_ltr, the edit cannot be translated onto the current map, so into_cmd bails.","triggerScenarios":"Calling Edits::apply/into_cmd where a saved EditRoad's lanes_ltr length != the current road's lane count (num_current), typically after the basemap was regenerated from changed OSM data.","commonSituations":"OSM changes added or removed a lane on an edited road; loading long-lived untitled/persistent edits across map re-imports; applying persistent edits after a map version upgrade.","solutions":["Regenerate the map from the OSM data matching the edits, then re-apply.","Delete the stored perma edit for that road and redo the lane change in the app.","Update the saved EditRoad's lanes_ltr to match the current lane count before applying."],"exampleFix":"// before: stale persisted edit\n{ \"lanes_ltr\": [sidewalk, driving, driving] }\n// after: match the road's current 4 lanes\n{ \"lanes_ltr\": [sidewalk, driving, driving, parking] }","handlingStrategy":"validation","validationCode":"// compare persisted edit lane count to the current road before applying\nlet r = map.get_r(id);\nif r.lanes_ltr().len() != saved.lanes_ltr.len() {\n    bail!(\"road {} lane count changed; redo this edit\", id);\n}","typeGuard":null,"tryCatchPattern":"match edits.apply(map) {\n    Ok(()) => (),\n    Err(err) if err.to_string().contains(\"number of lanes\") => {\n        error!(\"persistent edit stale, clearing it: {}\", err);\n        edits.commands.clear();\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Clear or refresh persistent edits when regenerating a map.","After OSM lane changes, manually redo lane edits for affected roads.","Warn users at startup when stored edits no longer match the loaded map."],"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"}