a-b-street/abstreet · error
's road doesn't point to dst_i at all
Error message
{:?}'s road doesn't point to dst_i at all What it means
During compat upgrade of a ReverseLane command, the code determines which direction the edited road must point by comparing dst_i with the road's src_i/dst_i. If the destination intersection is not an endpoint of the road at all, the command's assumptions are broken relative to the current map and upgrade bails.
Solutions
- Remove the stale ReverseLane command from the edit JSON and re-apply the change manually.
- Regenerate or use the map version the edit was created against.
- Update the command's road/intersection IDs to match the current map topology.
Defensive patterns
Strategy: validation
Validate before calling
// verify dst_i is an endpoint of the road before loading let r = map.get_r(map.find_r_by_osm_id(cmd_id)?); let ok = cmd.dst_i == r.src_i || cmd.dst_i == r.dst_i;
Prevention
- Re-verify road endpoints after every map regeneration before replaying edits.
- Store the map name in each edit file and check it before loading.
- Watch for road split/merge changes in OSM import diffs.
When it happens
Trigger: Loading an old edit file whose ReverseLane references a road whose endpoints changed (road split/merged after map regeneration), so obj.dst_i matches neither get_r(r).dst_i nor src_i.
Common situations: Applying edits saved months ago to a freshly regenerated map where OSM geometry changes split or rewired roads; replaying edits across 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
- 's road already points to dst_i
- speed limit has changed
- access restrictions have changed
- None of the edits apply to this map
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/5481a40fdbab941a.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/edits/compat.rs:238
if let Some(obj) = cmd.remove("ChangeLaneType") {
let obj: ChangeLaneType = serde_json::from_value(obj).unwrap();
let (r, idx) = obj.id.lookup(map)?;
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 {View on GitHub (pinned to 0964f29315)