a-b-street/abstreet · error

Stop position wasn't close to a sidewalk

Error message

Stop position {} wasn't close to a sidewalk

What it means

A GTFS stop's position must be within snapping distance of a sidewalk to place a transit stop. If FindClosest found no sidewalk near stop.position, create_stop bails because the stop cannot be anchored to the pedestrian network.

Solutions

  1. Verify the GTFS feed matches the map's area and projection; fix stop coordinates.
  2. Increase the sidewalk snap distance threshold in create_stop for the feed.
  3. Skip or manually relocate the offending stop in the GTFS data.
Defensive patterns

Strategy: validation

Validate before calling

let snap = sidewalk_finder.closest_pt(stop.position, snap_threshold);
if snap.is_none() { /* skip stop: not near any sidewalk */ }

Try / catch

match create_stop(map, stop, vehicle) {
    Err(e) if e.to_string().contains("wasn't close to a sidewalk") => {
        warn!("stop {} off the pedestrian network", stop.gtfs_id); continue;
    }
    other => other?,
}

Prevention

When it happens

Trigger: finalize_transit -> create_stop where the GTFS stop's lat/lng, projected into the map, is farther from any sidewalk than the snap threshold — e.g. coordinates slightly off (wrong projection) or stops placed in parking lots/medians away from sidewalks.

Common situations: Importing GTFS feeds for a different city than the map; GTFS stop_to_map projection drift at map edges; stops defined mid-block far from sidewalk geometry.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at map_model/src/make/transit.rs:95

                    id,
                    name: stop.name.clone(),
                    gtfs_id: stop.gtfs_id.clone(),
                    driving_pos,
                    sidewalk_pos: *sidewalk_pos,
                    is_train_stop: vehicle == PathConstraints::Train,
                },
            );
            gtfs_to_stop_id.insert(stop.gtfs_id.clone(), id);
            Ok(())
        } else {
            bail!(
                "Couldn't find a lane for {:?} next to sidewalk {}",
                vehicle,
                sidewalk_lane
            );
        }
    } else {
        bail!("Stop position {} wasn't close to a sidewalk", stop.position);
    }
}

struct BorderSnapper {
    bus_incoming_borders: FindClosest<LaneID>,
    bus_outgoing_borders: FindClosest<LaneID>,
    train_incoming_borders: FindClosest<LaneID>,
    train_outgoing_borders: FindClosest<LaneID>,
}

impl BorderSnapper {
    fn new(map: &Map) -> BorderSnapper {
        let mut snapper = BorderSnapper {
            bus_incoming_borders: FindClosest::new(),
            bus_outgoing_borders: FindClosest::new(),
            train_incoming_borders: FindClosest::new(),
            train_outgoing_borders: FindClosest::new(),
        };

View on GitHub (pinned to 0964f29315)