a-b-street/abstreet · error

number of lanes in is now, but in the edits

Error message

number of lanes in {} is {} now, but {} in the edits

What it means

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.

Solutions

  1. Regenerate the map from the OSM data matching the edits, then re-apply.
  2. Delete the stored perma edit for that road and redo the lane change in the app.
  3. Update the saved EditRoad's lanes_ltr to match the current lane count before applying.

Example fix

// before: stale persisted edit
{ "lanes_ltr": [sidewalk, driving, driving] }
// after: match the road's current 4 lanes
{ "lanes_ltr": [sidewalk, driving, driving, parking] }
Defensive patterns

Strategy: validation

Validate before calling

// compare persisted edit lane count to the current road before applying
let r = map.get_r(id);
if r.lanes_ltr().len() != saved.lanes_ltr.len() {
    bail!("road {} lane count changed; redo this edit", id);
}

Try / catch

match edits.apply(map) {
    Ok(()) => (),
    Err(err) if err.to_string().contains("number of lanes") => {
        error!("persistent edit stale, clearing it: {}", err);
        edits.commands.clear();
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/102ccd821cddf1ae. Report an issue: GitHub.

Appendix: source

Thrown at map_model/src/edits/perma.rs:121

impl PermanentEditCmd {
    pub fn into_cmd(self, map: &Map) -> Result<EditCmd> {
        match self {
            PermanentEditCmd::ChangeRoad { r, new, old } => {
                let id = map.find_r_by_osm_id(r)?;
                let num_current = map.get_r(id).lanes.len();
                // The basemap changed -- it'd be pretty hard to understand the original
                // intent of the edit.
                if num_current != old.lanes_ltr.len() {
                    if IGNORE_OLD_LANES {
                        warn!("Lanes in {r} have changed since the edits, but keeping the edits anyway");
                        return Ok(EditCmd::ChangeRoad {
                            r: id,
                            new,
                            // Note we change 'old' to match the current basemap
                            old: EditRoad::get_orig_from_osm(map.get_r(id), map.get_config()),
                        });
                    } else {
                        bail!(
                            "number of lanes in {} is {} now, but {} in the edits",
                            r,
                            num_current,
                            old.lanes_ltr.len()
                        );
                    }
                }
                Ok(EditCmd::ChangeRoad { r: id, new, old })
            }
            PermanentEditCmd::ChangeIntersection { i, new, old } => {
                let id = map.find_i_by_osm_id(i)?;
                Ok(EditCmd::ChangeIntersection {
                    i: id,
                    new: new
                        .with_permanent(id, map)
                        .with_context(|| format!("new ChangeIntersection of {} invalid", i))?,
                    old: old
                        .with_permanent(id, map)

View on GitHub (pinned to 0964f29315)