a-b-street/abstreet · error
Empty path between stops
Error message
Empty path between stops: {} What it means
After pathfinding between consecutive transit stops, all_paths checks each path for emptiness; an empty path means pathfind returned successfully but produced no steps, which cannot represent a drivable leg between stops. The library bails with the PathRequest echoed so the developer can locate the failing stop pair.
Solutions
- Inspect the PathRequest in the message and check whether its start/end snap to the same position; adjust stop placement.
- Verify the roads between the stops are connected and drivable in the current map.
- Remove or relocate the degenerate stop in the route definition.
- Rebuild/re-import the map if its connectivity was changed after routes were defined.
Example fix
// before let stops = vec![stop_a, stop_a.clone()]; // same position twice // after let stops = vec![stop_a, stop_b_distinct];
Defensive patterns
Strategy: validation
Validate before calling
for pair in stops.windows(2) {
if pair[0] == pair[1] { return Err("duplicate/degenerate stop".into()); }
}
// also check map connectivity between stop roads via map.pathfind on the request Try / catch
match route.all_paths(&map) {
Err(e) if e.to_string().starts_with("Empty path") => {
let req = parse_req_from(&e);
// relocate or drop the degenerate stop, then rebuild
}
other => other?,
} Prevention
- Reject duplicate or coincident stops when defining routes.
- After map edits, re-verify connectivity between all consecutive stops.
- Rebuild transit routes whenever the map version changes.
When it happens
Trigger: create_route / create_empty_route on a TransitRoute where map.pathfind(req) returns Ok but the path contains zero steps for some stop pair (map_model/src/objects/transit.rs:123) — typically when start and end positions effectively coincide or are unreachable but pathfind doesn't reject them.
Common situations: Degenerate stop placement (both stops at the same spot), a road isolated by map edits, or a path request whose start and end snap to the same lane position after map changes.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No transit route from
- Two consecutive stops are on the same road, but they travel…
- Transit route will warp from
- can't figure out PathRequest from
- no path found
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/d4b96fdf96c00d95.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/objects/transit.rs:123
}
/// Entry i is the path to drive to stop i. The very last entry is to drive from the last step
/// to the place where the vehicle vanishes.
pub fn all_paths(&self, map: &Map) -> Result<Vec<Path>> {
let mut paths = Vec::new();
for req in self.all_path_requests(map) {
if req.start.lane().road == req.end.lane().road
&& req.start.dist_along() > req.end.dist_along()
{
bail!(
"Two consecutive stops are on the same road, but they travel backwards: {}",
req
);
}
let path = map.pathfind(req)?;
if path.is_empty() {
bail!("Empty path between stops: {}", path.get_req());
}
paths.push(path);
}
for pair in paths.windows(2) {
if pair[0].get_req().end != pair[1].get_req().start {
bail!(
"Transit route will warp from {} to {}",
pair[0].get_req().end,
pair[1].get_req().start
);
}
}
Ok(paths)
}
pub fn plural_noun(&self) -> &'static str {View on GitHub (pinned to 0964f29315)