a-b-street/abstreet · warning

No road within of

Error message

No road within {} of {}

What it means

The find-closest-road command builds a nearest-neighbor index over all roads and searches within a caller-provided threshold (in meters). If no road's center points lie within threshold of the given position, the search returns None and the server bails with this message showing the threshold and input position.

Solutions

  1. Increase threshold_meters to cover GPS noise and distance to the nearest road.
  2. Verify the position is inside the map's GPS bounds and uses the expected coordinate format (lon/lat as the endpoint expects).
  3. Check you loaded the correct map for these coordinates.
  4. If no road should exist there, treat the error as 'not on the road network' rather than a bug.

Example fix

// before
const road = await post("/geo/find-closest-road", { pt, threshold_meters: 5 });
// after
let road;
try {
  road = await post("/geo/find-closest-road", { pt, threshold_meters: 5 });
} catch (e) {
  road = await post("/geo/find-closest-road", { pt, threshold_meters: 50 });
}
Defensive patterns

Strategy: fallback

Validate before calling

// ensure the point projects inside the map bounds
if (!map.gps_bounds.contains(pt)) throw new Error("point outside map");

Try / catch

try {
  road = await post("/geo/find-closest-road", { pt, threshold_meters: t });
} catch (e) {
  if (String(e).startsWith("No road within")) road = null; // treat as off-network
}

Prevention

When it happens

Trigger: The road-matching endpoint with threshold_meters=t and a position whose projected map point is farther than t meters from every road's center_pts.

Common situations: GPS coordinates outside the map bounds or projected incorrectly; coordinates belonging to a different map/city; threshold too small for GPS noise; passing lat/lon where map-space points are expected.

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

Appendix: source

Thrown at headless/src/main.rs:415

            Ok(abstutil::to_json(
                &map.edit_road_cmd(r, |_| {}).to_perma(map),
            ))
        }
        "/map/get-intersection-geometry" => {
            let i = IntersectionID(get("id")?.parse::<usize>()?);
            Ok(abstutil::to_json(&export_geometry(map, i)))
        }
        "/map/get-all-geometry" => Ok(abstutil::to_json(&map.export_geometry())),
        "/map/get-nearest-road" => {
            let pt = LonLat::new(get("lon")?.parse::<f64>()?, get("lat")?.parse::<f64>()?);
            let mut closest = FindClosest::new();
            for r in map.all_roads() {
                closest.add(r.id, r.center_pts.points());
            }
            let threshold = Distance::meters(get("threshold_meters")?.parse::<f64>()?);
            match closest.closest_pt(pt.to_pt(map.get_gps_bounds()), threshold) {
                Some((r, _)) => Ok(r.0.to_string()),
                None => bail!("No road within {} of {}", threshold, pt),
            }
        }
        _ => Err(anyhow!("Unknown command")),
    }
}

// TODO I think specifying the API with protobufs or similar will be a better idea.

#[derive(Serialize)]
struct FinishedTrip {
    id: TripID,
    person: PersonID,
    duration: Option<Duration>,
    distance_crossed: Distance,
    mode: TripMode,
}

#[derive(Serialize)]

View on GitHub (pinned to 0964f29315)