a-b-street/abstreet · error · anyhow::Error
biking to a different part of
Error message
biking to a different part of {} is silly, why not walk? What it means
ped_ready_to_bike handles a cyclist at a car/bike handoff point. When the computed bike PathRequest starts and ends on the same lane, routing a bike trip would be a pointless ride within one lane, so the code deliberately returns this error instead of pathfinding. The TODO in source indicates the trip should have been converted to walking earlier.
Solutions
- Convert such trips to walking before scheduling (as schedule_trip does), per the TODO.
- Filter out bike trips whose start and end lane are identical during trip generation.
- Adjust trip origin/destination sampling so bike trips span meaningful distance.
- If hit interactively, treat it as a signal the trip should have been a walking trip.
Example fix
// before
let req = PathRequest::vehicle(driving_pos, end, PathConstraints::Bike);
// after: convert short trips to walking at scheduling time
if driving_pos.lane() == end.lane() {
// schedule a walking TripSpec instead of a biking one
return schedule_walking_trip(...);
} Defensive patterns
Strategy: validation
Validate before calling
// Before scheduling a bike trip, ensure the lanes differ
if driving_pos.lane() == end.lane() {
// schedule as walking instead of biking
return schedule_walking_trip(origin, destination);
} Try / catch
// Treat this error as a signal to convert to walking
match ped_ready_to_bike(...) {
Err(e) if e.to_string().contains("why not walk?") => convert_to_walking(),
other => other,
} Prevention
- Filter same-lane origin/destination pairs during trip generation
- Convert trivially-short bike trips to walking at schedule time, as schedule_trip does
- Respect minimum sensible trip distance per mode in synthetic data
- Unit-test ped_ready_to_bike with same-lane requests to keep the guard in place
When it happens
Trigger: A bike trip (via TripSpec / ped_ready_to_bike in trips.rs) whose driving_pos and end resolve to PathRequests with identical start.lane() and end.lane(), e.g., origin and destination buildings adjacent to the same lane.
Common situations: Very short bike trips between nearby buildings on the same street; synthetic trip generation that doesn't filter out sub-lane-length bike trips; maps with sparse building coverage along a single lane.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Car with one-step route
- can't figure out PathRequest from
- can't fulfill
- can't start a trip from
- can't end walking at
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/3203b6ebd2f9d9f4.
Report an issue: GitHub.
Appendix: source
Thrown at sim/src/trips.rs:613
let end = if let Some(end) = drive_to.goal_pos(PathConstraints::Bike, ctx.map) {
end
} else {
let trip = trip.id;
self.cancel_trip(
now,
trip,
format!("no bike connection at {:?}", drive_to),
None,
ctx,
);
return;
};
let req = PathRequest::vehicle(driving_pos, end, PathConstraints::Bike);
let maybe_router = if req.start.lane() == req.end.lane() {
// TODO Convert to a walking trip! Ideally, do this earlier and convert the trip to
// walking, like schedule_trip does
Err(anyhow!(
"biking to a different part of {} is silly, why not walk?",
req.start.lane()
))
} else {
ctx.map
.pathfind(req)
.map(|path| drive_to.make_router(bike, path, ctx.map))
};
match maybe_router {
Ok(router) => {
ctx.scheduler.push(
now,
Command::SpawnCar(
CreateCar::for_appearing(
self.people[trip.person.0].get_vehicle(bike),
router,
trip.id,
trip.person,View on GitHub (pinned to 0964f29315)