a-b-street/abstreet · error
Starting on inner piece of a loop road
Error message
Starting on inner piece of a loop road
What it means
The start lane is on a loop road (a road whose src and dst intersection are the same), but on the inner direction that isn't represented among the intersection's sorted road sides. Tracing from such a lane cannot produce a valid perimeter, so the library refuses the start point.
Solutions
- Pick a different lane on the loop road whose side appears in the intersection's sorted road sides.
- Add the loop road to the `skip` set and start tracing elsewhere.
- If you must trace loops, handle them specially outside single_block (the library explicitly doesn't support inner loop starts).
Example fix
// before
let perimeter = Perimeter::single_block(map, some_lane_on_loop, &skip)?;
// after
let r = map.get_parent(some_lane_on_loop);
if r.src_i == r.dst_i {
some_lane_on_loop = pick_outer_loop_lane(map, r.id); // side present in sorted road sides
}
let perimeter = Perimeter::single_block(map, some_lane_on_loop, &skip)?; Defensive patterns
Strategy: validation
Validate before calling
let r = map.get_parent(start);
if r.src_i == r.dst_i {
let i = map.get_i(r.src_i);
let side = map.get_l(start).get_nearest_side_of_road(map);
anyhow::ensure!(i.get_road_sides_sorted(map).contains(&side), "inner loop start");
} Type guard
fn is_inner_loop_start(map: &Map, start: LaneID) -> bool {
let r = map.get_parent(start);
if r.src_i != r.dst_i { return false; }
let side = map.get_l(start).get_nearest_side_of_road(map);
!map.get_i(r.src_i).get_road_sides_sorted(map).contains(&side)
} Prevention
- Detect loop roads (src_i == dst_i) before choosing start lanes.
- Prefer outer-direction lanes on roundabouts/loop ramps.
When it happens
Trigger: Calling Perimeter::single_block with a start lane whose parent road is a loop (get_parent(start).src_i == dst_i) and where i.get_road_sides_sorted(map) does not contain the lane's nearest road side.
Common situations: Roundabouts and loop ramps in OSM data frequently produce one-way loop roads; picking an arbitrary lane on such a road as the trace start hits the inner direction.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Started on a road we shouldn't trace
- hit the map boundary at
- Looped back on the same road, but not at a dead-end
- Infinite loop starting from
- No common roads
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/8649626a1957e46c.
Report an issue: GitHub.
Appendix: source
Thrown at blockfinding/src/lib.rs:61
/// Starting at any lane, snap to the nearest side of that road, then begin tracing a single
/// block, with no interior roads. This will fail if a map boundary is reached. The results are
/// unusual when crossing the entrance to a tunnel or bridge, and so `skip` is used to avoid
/// tracing there.
pub fn single_block(map: &Map, start: LaneID, skip: &HashSet<RoadID>) -> Result<Perimeter> {
let mut roads = Vec::new();
let start_road_side = map.get_l(start).get_nearest_side_of_road(map);
if skip.contains(&start_road_side.road) {
bail!("Started on a road we shouldn't trace");
}
// We may start on a loop road on the "inner" direction
{
let start_r = map.get_parent(start);
if start_r.src_i == start_r.dst_i {
let i = map.get_i(start_r.src_i);
if !i.get_road_sides_sorted(map).contains(&start_road_side) {
bail!("Starting on inner piece of a loop road");
}
}
}
// We need to track which side of the road we're at, but also which direction we're facing
let mut current_road_side = start_road_side;
let mut current_intersection = map.get_l(start).dst_i;
loop {
let i = map.get_i(current_intersection);
if i.is_border() {
bail!("hit the map boundary at {}", i.orig_id);
}
let mut sorted_roads = i.get_road_sides_sorted(map);
sorted_roads.retain(|id| !skip.contains(&id.road));
let idx = sorted_roads
.iter()
.position(|x| *x == current_road_side)View on GitHub (pinned to 0964f29315)