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

  1. Inspect the PathRequest in the message and check whether its start/end snap to the same position; adjust stop placement.
  2. Verify the roads between the stops are connected and drivable in the current map.
  3. Remove or relocate the degenerate stop in the route definition.
  4. 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

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


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)