a-b-street/abstreet · error
must_get_sidewalk broken by
Error message
must_get_sidewalk broken by {} ({}). Found lanes {:?} What it means
DirectedRoadID::must_get_sidewalk asserts a directed road has exactly one walkable child lane. The invariant breaks if a road has zero or multiple walkable lanes (e.g. two sidewalks or a footway merged into the road's children), so it panics listing the found lanes.
Solutions
- Inspect the listed lanes; find which edit or import step created the extra/missing walkable lane and revert it.
- Use Road::children / filter for walkable lanes instead of assuming exactly one, and pick the nearest.
- Fix OSM tags so each side of the road has at most one sidewalk.
- Replace must_get_sidewalk usages with find_closest_lane(|l| l.is_walkable()) in your own code paths.
Example fix
// before
let sidewalk = dir_road.must_get_sidewalk(map);
// after
if let Some(l) = map.get_r(dir_road.road).find_closest_lane(dir_road.lane_id, |l| l.is_walkable(), map) { /* use l */ } else { anyhow::bail!("no sidewalk on {}", dir_road.road) }; Defensive patterns
Strategy: validation
Validate before calling
// count walkable children before calling
let walkable: Vec<_> = map.get_r(dir.road).children(dir.dir).iter()
.filter(|(_, lt)| lt.is_walkable()).collect();
assert_eq!(walkable.len(), 1, "road {} has {} walkable lanes", dir.road, walkable.len()); Prevention
- Prefer find_closest_lane with an is_walkable filter over must_get helpers
- Review map edits that convert car lanes to sidewalks
- Validate imported maps for multi-sidewalk roads before running sims
When it happens
Trigger: Calling must_get_sidewalk on a road whose lane list contains 0 or >1 walkable lanes in the given direction — commonly after map edits (parking-to-sidewalk conversions) or on oddly tagged OSM ways.
Common situations: Pedestrian routing and SidewalkPOC/traversal code paths that assume one sidewalk per road side; user edits (e.g. through the map editor) converting car lanes to sidewalks.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- doesn't contain
- doesn't touch
- doesn't contain both and
- Some IndividTrip wasn't associated with a Person?!
- ( ) is a border, but is connected to >1 road
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/b7bbe0c0b77f3d2c.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/objects/road.rs:106
}
}
/// Strict for bikes. If there are bike lanes, not allowed to use other lanes.
pub fn lanes(self, constraints: PathConstraints, map: &Map) -> Vec<LaneID> {
let r = map.get_r(self.road);
constraints.filter_lanes(r.children(self.dir).iter().map(|(l, _)| *l).collect(), map)
}
/// Get the only sidewalk or shoulder on this side of the road, and panic otherwise.
pub fn must_get_sidewalk(self, map: &Map) -> LaneID {
let mut found = Vec::new();
for (l, lt) in map.get_r(self.road).children(self.dir) {
if lt.is_walkable() {
found.push(l);
}
}
if found.len() != 1 {
panic!(
"must_get_sidewalk broken by {} ({}). Found lanes {:?}",
self,
map.get_r(self.road).orig_id,
found
);
}
found[0]
}
/// Does this directed road have any lanes of a certain type?
pub fn has_lanes(self, lane_type: LaneType, map: &Map) -> bool {
for (_, lt) in map.get_r(self.road).children(self.dir) {
if lt == lane_type {
return true;
}
}
false
}View on GitHub (pinned to 0964f29315)