a-b-street/abstreet · error · anyhow::Error

No border for

Error message

No border for {}

What it means

When an external trip endpoint's GPS position is outside the map boundary, import maps it to the nearest border intersection for the trip's mode. If borders.for_mode(mode) returns an empty candidate list (no incoming borders for an origin, or no outgoing for a destination), min_by_key receives an empty iterator and this error is raised naming the mode's ongoing verb.

Solutions

  1. Ensure the map has border intersections for all modes used by external data (rebuild including boundary roads).
  2. Filter external trips to modes supported by the map's borders before import.
  3. Fall back to snapping the GPS point to any-mode borders or the nearest building.
  4. Check borders.for_mode configuration and the mode's ongoing_verb to confirm the intended mode is registered.

Example fix

// before
.ok_or_else(|| anyhow!("No border for {}", mode.ongoing_verb()))?
// after
match candidates.iter().min_by_key(|b| b.gps_pos.fast_dist(gps)) {
    Some(border) => Ok(TripEndpoint::Border(border.i)),
    None => Ok(TripEndpoint::Building(closest_building)), // fallback
}
Defensive patterns

Strategy: validation

Validate before calling

// Check border availability for the mode before importing
let (incoming, outgoing) = borders.for_mode(mode);
if is_origin && incoming.is_empty() {
    // skip or re-route this trip
}

Try / catch

// Catch and skip/re-mode the trip
match import(...) {
    Err(e) if e.to_string().starts_with("No border for") => skip_trip_with_reason(e),
    other => other,
}

Prevention

When it happens

Trigger: Importing a trip whose origin GPS is outside the map while the map has no incoming borders for that mode (or destination outside with no outgoing borders) — e.g., a mode like biking with no registered border crossings.

Common situations: Maps with few or no border connections for a transport mode; external datasets whose trips approach from directions where no border exists; misconfigured map building that excluded major roads crossing the boundary.

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/a99a5a092f618a75. Report an issue: GitHub.

Appendix: source

Thrown at synthpop/src/external.rs:66

        let borders = MapBorders::new(map);

        let lookup_pt = |endpt, is_origin, mode| match endpt {
            ExternalTripEndpoint::TripEndpoint(endpt) => Ok(endpt),
            ExternalTripEndpoint::Position(gps) => {
                let pt = gps.to_pt(map.get_gps_bounds());
                if map.get_boundary_polygon().contains_pt(pt) {
                    match closest.closest_pt(pt, Distance::meters(100.0)) {
                        Some((x, _)) => Ok(x),
                        None => Err(anyhow!("No building within 100m of {}", gps)),
                    }
                } else {
                    let (incoming, outgoing) = borders.for_mode(mode);
                    let candidates = if is_origin { incoming } else { outgoing };
                    Ok(TripEndpoint::Border(
                        candidates
                            .iter()
                            .min_by_key(|border| border.gps_pos.fast_dist(gps))
                            .ok_or_else(|| anyhow!("No border for {}", mode.ongoing_verb()))?
                            .i,
                    ))
                }
            }
        };

        let mut results = Vec::new();
        for person in input {
            let mut spec = PersonSpec {
                orig_id: None,
                trips: Vec::new(),
            };
            for trip in person.trips {
                if trip.departure < Time::START_OF_DAY {
                    if skip_problems {
                        warn!(
                            "Skipping trip with negative departure time {:?}",
                            trip.departure

View on GitHub (pinned to 0964f29315)