a-b-street/abstreet · error
access restrictions have changed
Error message
{:?} access restrictions have changed What it means
When upgrading a ChangeAccessRestrictions command, the recorded old access restrictions (obj.old) are compared against the road's current access_restrictions. A mismatch means the edit's precondition is stale, so upgrade bails instead of applying the change on the wrong baseline.
Solutions
- Update the command's `old` field in the edit JSON to the road's current access restrictions.
- Remove the stale command and re-apply the restriction change in the app.
- Regenerate the map to match the edit's recorded old restrictions.
Defensive patterns
Strategy: validation
Validate before calling
// confirm recorded old access restrictions match the current road
let r = map.find_r_by_osm_id(cmd.id)?;
if map.get_r_edit(r).access_restrictions != cmd.old { /* update or drop cmd */ } Prevention
- Recreate access-restriction edits after each map regeneration.
- Avoid stacking edits from different basemap versions.
- Diff road access restrictions between map builds before loading old edits.
When it happens
Trigger: Loading an edit file whose ChangeAccessRestrictions.old differs from road.access_restrictions in the current map — after basemap regeneration, OSM updates, or prior edits changed restrictions.
Common situations: Replaying old edits onto a regenerated map; applying the same edit file twice; sharing edit files between different map versions.
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
- lane type has changed
- speed limit has changed
- 's road doesn't point to dst_i at all
- 's road already points to dst_i
- number of lanes in is ( fwd, back) now, but ( , ) in the…
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/2fcb2f1a8ea421ff.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/edits/compat.rs:257
};
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();
} else {
commands.push(orig);
}
}
for (r, new) in modified {
let old = map.get_r_edit(r);
commands
.push(serde_json::to_value(EditCmd::ChangeRoad { r, old, new }.to_perma(map)).unwrap());
}
value.as_object_mut().unwrap()["commands"] = Value::Array(commands);
Ok(())
}
// a3af291b2966c89d63b719e41821705077d063d2 added a map-wide merge_zones field
fn fix_merge_zones(value: &mut Value) {View on GitHub (pinned to 0964f29315)