a-b-street/abstreet · error

's road already points to dst_i

Error message

{:?}'s road already points to dst_i

What it means

When upgrading a ReverseLane command, if the target road's lane already points in the direction of dst_i (the change would be a no-op), the upgrade rejects the command because re-applying it is meaningless and likely indicates the edit was already applied.

Solutions

  1. Drop the redundant ReverseLane command from the edit JSON — the desired state already holds.
  2. Regenerate the map to reset the lane direction, then re-apply the edit.
  3. If intentional, invert the command or remove it and re-create the edit.
Defensive patterns

Strategy: validation

Validate before calling

// skip ReverseLane if the lane already points toward dst_i
let dir = if dst_i == map.get_r(r).dst_i { Direction::Fwd } else { Direction::Back };
if map.get_r_edit(r).lanes_ltr[idx].dir == dir { /* drop redundant cmd */ }

Prevention

When it happens

Trigger: Loading an edit file whose ReverseLane command targets a lane whose current dir already equals the edits_dir computed from dst_i — typically after the edit was already applied or the basemap changed to match.

Common situations: Double-applying an edit file; loading an edit after the change became part of the basemap regeneration.

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/444536f10bc775b9. Report an issue: GitHub.

Appendix: source

Thrown at map_model/src/edits/compat.rs:241

            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));
            if road.lanes_ltr[idx].lt != obj.orig_lt {
                bail!("{:?} lane type has changed", obj);
            }
            road.lanes_ltr[idx].lt = obj.lt;
        } else if let Some(obj) = cmd.remove("ReverseLane") {
            let obj: ReverseLane = serde_json::from_value(obj).unwrap();
            let (r, idx) = obj.l.lookup(map)?;
            let dst_i = map.find_i_by_osm_id(obj.dst_i)?;
            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));
            let edits_dir = if dst_i == map.get_r(r).dst_i {
                Direction::Fwd
            } else if dst_i == map.get_r(r).src_i {
                Direction::Back
            } else {
                bail!("{:?}'s road doesn't point to dst_i at all", obj);
            };
            if road.lanes_ltr[idx].dir == edits_dir {
                bail!("{:?}'s road already points to dst_i", obj);
            }
            road.lanes_ltr[idx].dir = edits_dir;
        } else if let Some(obj) = cmd.remove("ChangeSpeedLimit") {
            let obj: ChangeSpeedLimit = serde_json::from_value(obj).unwrap();
            let r = map.find_r_by_osm_id(obj.id)?;
            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));
            if road.speed_limit != obj.old {
                bail!("{:?} speed limit has changed", obj);
            }
            road.speed_limit = obj.new;
        } else if let Some(obj) = cmd.remove("ChangeAccessRestrictions") {
            let obj: ChangeAccessRestrictions = serde_json::from_value(obj).unwrap();
            let r = map.find_r_by_osm_id(obj.id)?;
            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));
            if road.access_restrictions != obj.old {
                bail!("{:?} access restrictions have changed", obj);
            }
            road.access_restrictions = obj.new.clone();

View on GitHub (pinned to 0964f29315)