a-b-street/abstreet · error · anyhow::Error
No building within 100m of
Error message
No building within 100m of {} What it means
synthpop's import converts an external trip endpoint given as a GPS position into a TripEndpoint. If the GPS point lies inside the map boundary but no building is within 100 meters (per the prebuilt ClosestEdges structure), the conversion fails with this error. It guards against positions too far from any mapped building to snap to.
Solutions
- Snap such GPS points to the nearest border instead (the code already does this for outside-boundary points).
- Increase the 100m search radius in closest_pt when maps have sparse building coverage.
- Pre-filter external trip data to drop endpoints far from any building.
- Rebuild the map ensuring building extraction covers the area containing the trips.
Example fix
// before
match closest.closest_pt(pt, Distance::meters(100.0)) {
Some((x, _)) => Ok(x),
None => Err(anyhow!("No building within 100m of {}", gps)),
}
// after
match closest.closest_pt(pt, Distance::meters(100.0)).or_else(|| closest.closest_pt(pt, Distance::meters(500.0))) {
Some((x, _)) => Ok(x),
None => Ok(TripEndpoint::Border(nearest_border)), // fallback
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-filter external trips before import
fn snap_ok(gps: &GPS, map: &Map) -> bool {
let pt = gps.to_pt(map.get_gps_bounds());
!map.get_boundary_polygon().contains_pt(pt) || pt.is_within(<> /* 100m of some building */)
} Try / catch
// Catch and snap to the nearest border instead
match import(...) {
Err(e) if e.to_string().starts_with("No building within 100m") => {
import_as_border_trip(...) // reuse outside-boundary logic
}
other => other,
} Prevention
- Pre-filter GPS points far from buildings before import
- Keep the map's building extraction covering the full trip-data extent
- Reuse the existing border-snap fallback for inside-boundary misses
- Log dropped or re-snapped coordinates to audit data quality
When it happens
Trigger: Importing external trip data (e.g., from a data source like元气city/seattle data) where an origin/destination GPS coordinate is inside the map polygon but more than 100m from the nearest building in closest_pt's index.
Common situations: GPS coordinates in parks, water bodies, industrial areas, or newly developed zones with no buildings in the map; maps built with building filtering that removed nearby buildings; slightly-out-of-bounds coordinates that pass the polygon check.
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
- Some trip has negative departure time
- No border for
- Traffic signal assignment for
- {}
- TODO: handle working and living in the same building
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/df37c4c5e1e90606.
Report an issue: GitHub.
Appendix: source
Thrown at synthpop/src/external.rs:57
pub fn import(
map: &Map,
input: Vec<ExternalPerson>,
skip_problems: bool,
) -> Result<Vec<PersonSpec>> {
let mut closest: FindClosest<TripEndpoint> = FindClosest::new();
for b in map.all_buildings() {
closest.add_polygon(TripEndpoint::Building(b.id), &b.polygon);
}
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 {View on GitHub (pinned to 0964f29315)