{"record":{"id":"e19108af0f1c96c1","repo":"a-b-street/abstreet","slug":"looped-back-on-the-same-road-but-not-at-a-dead-end","errorCode":null,"errorMessage":"Looped back on the same road, but not at a dead-end","messagePattern":"Looped back on the same road, but not at a dead-end","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"blockfinding/src/lib.rs","lineNumber":90,"sourceCode":"                bail!(\"hit the map boundary at {}\", i.orig_id);\n            }\n            let mut sorted_roads = i.get_road_sides_sorted(map);\n            sorted_roads.retain(|id| !skip.contains(&id.road));\n\n            let idx = sorted_roads\n                .iter()\n                .position(|x| *x == current_road_side)\n                .unwrap() as isize;\n            // Do we go clockwise or counter-clockwise around the intersection? Well, unless we're\n            // at a dead-end, we want to avoid the other side of the same road.\n            let mut next = *wraparound_get(&sorted_roads, idx + 1);\n            assert_ne!(next, current_road_side);\n            if next.road == current_road_side.road {\n                next = *wraparound_get(&sorted_roads, idx - 1);\n                assert_ne!(next, current_road_side);\n                if next.road == current_road_side.road {\n                    if sorted_roads.len() != 2 {\n                        bail!(\"Looped back on the same road, but not at a dead-end\");\n                    }\n                }\n            }\n            roads.push(current_road_side);\n            current_road_side = next;\n            current_intersection = map\n                .get_r(current_road_side.road)\n                .other_endpt(current_intersection);\n\n            if current_road_side == start_road_side {\n                roads.push(start_road_side);\n                break;\n            }\n\n            if roads.len() > map.all_roads().len() {\n                bail!(\n                    \"Infinite loop starting from {start} ({})\",\n                    map.get_parent(start).orig_id","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/blockfinding/src/lib.rs#L72-L108","documentation":"During the perimeter walk, the trace stepped from an intersection back onto the same road side it arrived on, and even after stepping one further around the sorted road sides it's still on the same road. This is only valid at a dead-end intersection (exactly 2 roads left after filtering); otherwise the walking algorithm's assumption is broken, so it bails.","triggerScenarios":"single_block reaches an intersection where the clockwise next road side and the one after it both belong to the incoming road, and the filtered sorted_roads list has more than 2 entries — i.e. a same-road wraparound at a non-dead-end intersection.","commonSituations":"Degenerate OSM geometry: very short dual-carriageway links, slip lanes, or duplicate/parallel roads converging at an intersection; map edits or imports producing overlapping road sides.","solutions":["Inspect the intersection geometry in the map model for duplicate or zero-length roads and fix the map input.","Add the problematic road(s) to `skip` so the trace takes a different route.","Update the map import ( newer map_model may sort road sides differently); regenerate the map."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match Perimeter::single_block(map, start, &skip) {\n    Ok(p) => Some(p),\n    Err(e) => { warn!(\"trace failed from {:?}: {}\", start, e); None }\n}","preventionTips":["Validate map input for duplicate or degenerate roads at intersections.","Use skip sets for known-bad geometry like slip lanes."],"tags":["perimeter-tracing","geometry"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}