a-b-street/abstreet · error · anyhow::Error
can't fulfill
Error message
can't fulfill {} What it means
Map::pathfind_v2 delegates to the pathfinder and unwraps its Option<PathV2>; when the pathfinder cannot produce a path for the request, this error is thrown with the request printed. It is the standard 'no route exists for this PathRequest' failure, meaning no connected sequence of lanes respecting the request's constraints links start to goal.
Solutions
- Inspect the printed PathRequest and confirm start/goal are on connected lanes of the required type
- Retry without restrictive path constraints or with different RoutingParams
- Verify the map was rebuilt after edits so the pathfinder isn't stale (the assert guards this)
- Check graph connectivity between the endpoints before pathfinding, e.g. via should_use_transit or reachability probes
Example fix
// before
let path = map.pathfind(req).ok_or(anyhow!("no path"))?;
// after
let path = match map.pathfind(req.clone()) {
Ok(p) => p,
Err(e) => {
warn!("no path for {:?}: {}", req, e);
return None; // or fall back to a different mode
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
// probe connectivity before pathfinding
if map.should_use_transit(start, end).is_none() && req.end.lane().road == req.start.lane().road == false {
// consider checking reachability via a cheaper pathfind on a subset
} Try / catch
match map.pathfind(req.clone()) {
Ok(p) => p,
Err(e) if e.to_string().starts_with("can't fulfill") => {
warn!("unroutable: {}", e);
fallback_route_or_cancel()
}
Err(e) => return Err(e),
} Prevention
- Never assume any two positions are connected; always handle pathfinding failure
- Retry with relaxed constraints (no avoid-lists) on failure
- Rebuild maps after edits so the pathfinder matches the current graph
- Log the full PathRequest on failure for diagnosis
When it happens
Trigger: Calling map.pathfind(req) (which calls pathfind_v2) where PathfinderWise::pathfind returns None: start/end positions on disconnected parts of the graph, wrong path constraints (e.g. requiring a lane type the route can't use), or a stale pathfinder (pathfinder_dirty asserted).
Common situations: Routing between a building and a destination with no driving/walking connectivity; bus-only trips where no transit route connects the stops; requests built against an old map after edits; filtering out roads (e.g. avoid highways) that removes all routes.
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
- can't figure out PathRequest from
- Car with one-step route
- Empty path between stops
- no path found
- can't start a trip from
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/b8d06bd7add67266.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/map.rs:680
}
pub fn pathfind(&self, req: PathRequest) -> Result<Path> {
self.pathfind_v2(req)?.into_v1(self)
}
pub fn pathfind_with_params(
&self,
req: PathRequest,
params: &RoutingParams,
cache_custom: PathfinderCaching,
) -> Result<Path> {
self.pathfind_v2_with_params(req, params, cache_custom)?
.into_v1(self)
}
pub fn pathfind_v2(&self, req: PathRequest) -> Result<PathV2> {
assert!(!self.pathfinder_dirty);
self.pathfinder
.pathfind(req.clone(), self)
.ok_or_else(|| anyhow!("can't fulfill {}", req))
}
pub fn pathfind_v2_with_params(
&self,
req: PathRequest,
params: &RoutingParams,
cache_custom: PathfinderCaching,
) -> Result<PathV2> {
assert!(!self.pathfinder_dirty);
self.pathfinder
.pathfind_with_params(req.clone(), params, cache_custom, self)
.ok_or_else(|| anyhow!("can't fulfill {}", req))
}
pub fn should_use_transit(
&self,
start: Position,
end: Position,
) -> Option<(TransitStopID, Option<TransitStopID>, TransitRouteID)> {
assert!(!self.pathfinder_dirty);View on GitHub (pinned to 0964f29315)