{"record":{"id":"13d1e2e2a833b061","repo":"a-b-street/abstreet","slug":"no-transit-route-from-to-now-for-prevent-this-edit","errorCode":null,"errorMessage":"No transit route from {} to {} now for {}! Prevent this edit","messagePattern":"No transit route from (.+?) to (.+?) now for (.+?)! Prevent this edit","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/pathfind/walking.rs","lineNumber":386,"sourceCode":"    // transit vehicle to drive between the stops. Optimistically assume no waiting time at a stop.\n    for route in map.all_transit_routes() {\n        // TODO Also plug in border starts\n        for pair in route.stops.windows(2) {\n            let (stop1, stop2) = (map.get_ts(pair[0]), map.get_ts(pair[1]));\n            let req = PathRequest::vehicle(stop1.driving_pos, stop2.driving_pos, route.route_type);\n            let maybe_driving_cost = match route.route_type {\n                PathConstraints::Bus => bus_graph.pathfind(req, map).map(|p| p.get_cost()),\n                PathConstraints::Train => train_graph.pathfind(req, map).map(|p| p.get_cost()),\n                _ => unreachable!(),\n            };\n            if let Some(driving_cost) = maybe_driving_cost {\n                input_graph.add_edge(\n                    nodes.get(WalkingNode::RideTransit(stop1.id)),\n                    nodes.get(WalkingNode::RideTransit(stop2.id)),\n                    round(driving_cost),\n                );\n            } else {\n                panic!(\n                    \"No transit route from {} to {} now for {}! Prevent this edit\",\n                    stop1.driving_pos, stop2.driving_pos, route.long_name,\n                );\n            }\n        }\n\n        if let Some(l) = route.end_border {\n            let stop1 = map.get_ts(*route.stops.last().unwrap());\n            let req =\n                PathRequest::vehicle(stop1.driving_pos, Position::end(l, map), route.route_type);\n            let maybe_driving_cost = match route.route_type {\n                PathConstraints::Bus => bus_graph.pathfind(req, map).map(|p| p.get_cost()),\n                PathConstraints::Train => train_graph.pathfind(req, map).map(|p| p.get_cost()),\n                _ => unreachable!(),\n            };\n            if let Some(driving_cost) = maybe_driving_cost {\n                let border = map.get_i(map.get_l(l).dst_i);\n                input_graph.add_edge(","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/pathfind/walking.rs#L368-L404","documentation":"While building the walking/transit input graph, transit_input_graph connects each adjacent pair of stops along a transit route with an edge whose cost is the vehicle's driving time. If the driving pathfinder (bus or train graph) finds no route between the two stops' driving positions, the invariant that a route's consecutive stops are drivable is broken, and the code panics to prevent the map edit from being saved.","triggerScenarios":"make_input_graph called (typically during map import or an edit in the map editor) when a transit route's consecutive stops stop1 -> stop2 cannot be connected by a driving path of the route's type, e.g. after editing roads so the stops' driving lanes become disconnected.","commonSituations":"Hit when a user edits the map (removes/changes roads or bus lanes) and tries to save an edit that would strand adjacent transit stops; also occurs on faulty OSM imports where bus stops sit on disconnected driving roads.","solutions":["Undo the map edit that disconnected the two stops (the message says 'Prevent this edit')","Move one of the stops back onto a driving lane connected to the other stop before saving","Check the route's stop list for stops placed on sidewalks or non-driving lanes and fix their driving_pos","Verify with the map editor's connectivity/verify tools that all transit routes remain drivable before saving"],"exampleFix":"// before\nmatch bus_graph.pathfind(req, map) {\n    Some(p) => input_graph.add_edge(a, b, round(p.get_cost())),\n    None => panic!(\"No transit route from {} to {}\", stop1.driving_pos, stop2.driving_pos),\n}\n// after\nmatch bus_graph.pathfind(req, map) {\n    Some(p) => input_graph.add_edge(a, b, round(p.get_cost())),\n    None => bail!(\n        \"Cannot save edit: no driving path between stops {} and {} on route {}; reconnect or move the stops\",\n        stop1.driving_pos, stop2.driving_pos, route.long_name\n    ),\n}","handlingStrategy":"validation","validationCode":"for pair in route.stops.windows(2) {\n    let (s1, s2) = (map.get_ts(pair[0]), map.get_ts(pair[1]));\n    let req = PathRequest::vehicle(s1.driving_pos, s2.driving_pos, route.route_type);\n    if graph.pathfind(req, map).is_none() {\n        return Err(anyhow!(\"edit would strand route {} between {} and {}\", route.long_name, s1.driving_pos, s2.driving_pos));\n    }\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Ok(_) => commit_edit(),\n    Err(e) if e.to_string().contains(\"No transit route\") => {\n        warn!(\"Edit rejected: {}\", e);\n        undo_edit();\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Run the map editor's transit connectivity check before saving edits","Never place transit stops on lanes unreachable by the route's vehicle type","Re-verify all routes after road or bus-lane edits"],"tags":["rust","transit","pathfinding","map-edit","panic"],"backgroundTag":"invalid-state-transition","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}