{"record":{"id":"77e218f05944c404","repo":"a-b-street/abstreet","slug":"transit-route-will-warp-from-to","errorCode":null,"errorMessage":"Transit route will warp from {} to {}","messagePattern":"Transit route will warp from (.+?) to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/objects/transit.rs","lineNumber":130,"sourceCode":"            if req.start.lane().road == req.end.lane().road\n                && req.start.dist_along() > req.end.dist_along()\n            {\n                bail!(\n                    \"Two consecutive stops are on the same road, but they travel backwards: {}\",\n                    req\n                );\n            }\n\n            let path = map.pathfind(req)?;\n            if path.is_empty() {\n                bail!(\"Empty path between stops: {}\", path.get_req());\n            }\n            paths.push(path);\n        }\n\n        for pair in paths.windows(2) {\n            if pair[0].get_req().end != pair[1].get_req().start {\n                bail!(\n                    \"Transit route will warp from {} to {}\",\n                    pair[0].get_req().end,\n                    pair[1].get_req().start\n                );\n            }\n        }\n\n        Ok(paths)\n    }\n\n    pub fn plural_noun(&self) -> &'static str {\n        if self.route_type == PathConstraints::Bus {\n            \"buses\"\n        } else {\n            \"trains\"\n        }\n    }\n}","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/objects/transit.rs#L112-L148","documentation":"After collecting per-leg paths, all_paths verifies that consecutive paths are contiguous: the end of path[i] must equal the start of path[i+1]. A mismatch means the transit vehicle would teleport (\"warp\") between positions, so the route is rejected. This catches routes whose stop sequence is not a connected chain of drivable paths.","triggerScenarios":"create_route / create_empty_route where for some adjacent pair, pair[0].get_req().end != pair[1].get_req().start (map_model/src/objects/transit.rs:130) — e.g. the path from stop A ends at a location different from where the path to stop C begins.","commonSituations":"Stop lists edited out of order, stops on disconnected parts of the map after edits, or route definitions reused across different map versions whose paths changed.","solutions":["Check the two positions in the message; ensure the intermediate stop connects both legs — often the middle stop is unreachable so its leg silently deviates.","Reorder or insert stops so the sequence forms a continuous forward chain.","Recompute routes after any map geometry/connectivity changes.","Fix unreachable map segments (missing connections) that make one leg's path terminate elsewhere."],"exampleFix":"// before: route [A, C, B] where C is off the A->B corridor\nlet stops = vec![a, c, b];\n// after: order stops along the actual travel corridor\nlet stops = vec![a, b, c];","handlingStrategy":"validation","validationCode":"for pair in stops.windows(2) {\n    let req = PathRequest::vehicle(pair[0], pair[1], mode);\n    let path = map.pathfind(req)?;\n    if path.end() != next_leg_start(pair[1]) {\n        return Err(\"discontinuous stop chain\".into());\n    }\n}","typeGuard":null,"tryCatchPattern":"match route.all_paths(&map) {\n    Err(e) if e.to_string().starts_with(\"Transit route will warp\") => {\n        // recompute/reorder stops based on the two positions in the message\n    }\n    other => other?,\n}","preventionTips":["Keep stop lists sorted along the actual travel corridor.","Recompute all transit routes after any map geometry change.","Insert intermediate stops so legs share endpoints rather than skipping nodes."],"tags":["transit","routing","path-continuity","map-model"],"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"}