a-b-street/abstreet · error

Two consecutive stops are on the same road, but they travel…

Error message

Two consecutive stops are on the same road, but they travel backwards: {}

What it means

Transit route construction walks consecutive stop pairs and builds a path request for each. If two consecutive stops lie on the same road but the requested trip goes backwards along it (start.dist_along() > end.dist_along()), no forward path exists, so all_paths bails. The library refuses to synthesize U-turn or reversed travel for transit vehicles.

Solutions

  1. Reorder or remove the offending stop pair in the transit route so travel proceeds forward along the road.
  2. Move one of the stops to the opposite side / correctly directed road in the map editor.
  3. Split the route into two routes at the turnaround point, inserting a loop via different roads.
  4. Rebuild the map so the road is split at the stop, giving each stop its own correctly directed road.

Example fix

// before: stops A (dist 900) then B (dist 100) on same road
let route = TransitRoute::create_route(&map, vec![stop_a, stop_b])?;
// after: place stop B on the opposite-direction road or reorder
let route = TransitRoute::create_route(&map, vec![stop_b_opposite_dir, stop_a])?;
Defensive patterns

Strategy: validation

Validate before calling

for pair in stops.windows(2) {
    if pair[0].lane().road == pair[1].lane().road
        && pair[0].dist_along() > pair[1].dist_along() {
        return Err(format!("backwards pair on road {}", pair[0].lane().road));
    }
}

Try / catch

match TransitRoute::create_route(&map, stops) {
    Err(e) if e.to_string().starts_with("Two consecutive stops") => {
        // fix stop ordering/placement and retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: Creating a transit route (create_route / create_empty_route) where stop N and stop N+1 are on the same road but the vehicle must travel in reverse direction of the road's lane ordering, i.e. req.start.dist_along() > req.end.dist_along() (map_model/src/objects/transit.rs:115).

Common situations: Transit data (GTFS-like imports) where stops are placed by position rather than driving direction, or a route loops back along the same road; also bidirectional stops auto-assigned to the wrong side of the street.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/cb740297ec46ce2b. Report an issue: GitHub.

Appendix: source

Thrown at map_model/src/objects/transit.rs:115

            // Drive to the end of the lane with the last stop
            steps.push(PathRequest::vehicle(
                last_stop_pos,
                Position::end(last_stop_pos.lane(), map),
                self.route_type,
            ));
        }
        steps
    }

    /// 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

View on GitHub (pinned to 0964f29315)