{"record":{"id":"544f4047f3f580e7","repo":"a-b-street/abstreet","slug":"couldn-t-find-where-shape-enters-map","errorCode":null,"errorMessage":"couldn't find where shape enters map","messagePattern":"couldn't find where shape enters map","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"map_model/src/make/transit.rs","lineNumber":170,"sourceCode":"        .stops\n        .iter()\n        .filter_map(|gtfs_id| gtfs_to_stop_id.get(gtfs_id).cloned())\n        .collect();\n    if stops.is_empty() {\n        bail!(\"No valid stops\");\n    }\n    let border_snap_threshold = Distance::meters(30.0);\n\n    let start = if map.boundary_polygon.contains_pt(route.shape.first_pt()) {\n        map.get_ts(stops[0]).driving_pos.lane()\n    } else {\n        // Find the first time the route shape hits the map boundary\n        let entry_pt = *map\n            .boundary_polygon\n            .get_outer_ring()\n            .all_intersections(&route.shape)\n            .get(0)\n            .ok_or_else(|| anyhow!(\"couldn't find where shape enters map\"))?;\n        // Snap that to a border\n        let borders = if route.route_type == RawTransitType::Bus {\n            &snapper.bus_incoming_borders\n        } else {\n            &snapper.train_incoming_borders\n        };\n        match borders.closest_pt(entry_pt, border_snap_threshold) {\n            Some((l, _)) => l,\n            None => bail!(\n                \"Couldn't find a {:?} border near start {}\",\n                route.route_type,\n                entry_pt\n            ),\n        }\n    };\n\n    let end_border = if map.boundary_polygon.contains_pt(route.shape.last_pt()) {\n        None","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/make/transit.rs#L152-L188","documentation":"create_route must place the start of a transit route on the map boundary, computed as the first intersection between the raw GTFS route shape and the map's boundary polygon outer ring. If the shape never crosses the boundary, there is no entry point and this error is thrown. It means the route is judged to be entirely inside the map, so no incoming border can be chosen.","triggerScenarios":"Calling finalize_transit on a GTFS route whose shape polyline does not intersect map.boundary_polygon.get_outer_ring() — all_intersections(&route.shape) returns an empty Vec, so .get(0) is None.","commonSituations":"Importing a GTFS feed where a route was clipped so its shape stops just inside the boundary; shapes with only a single point inside the map; boundary polygon changed/simplified after shapes were generated; mis-projected shape coordinates.","solutions":["Verify the GTFS shape coordinates were projected with the same projection as the map boundary","Extend or extrapolate the shape beyond the map edge before intersection, or fall back to snapping the first shape point to the nearest incoming border","Skip such routes with a warning instead of failing the whole transit import","Re-check the map boundary polygon for gaps or simplification that excludes the shape"],"exampleFix":"// before\nlet entry_pt = *map.boundary_polygon.get_outer_ring().all_intersections(&route.shape).get(0).ok_or_else(|| anyhow!(\"couldn't find where shape enters map\"))?;\n// after\nlet entry_pt = match map.boundary_polygon.get_outer_ring().all_intersections(&route.shape).first() {\n    Some(pt) => *pt,\n    None => {\n        warn!(\"route {} never crosses the boundary; snapping first shape point to nearest border\", route.route_id);\n        snapper.nearest_incoming_border(&route.shape.first_pt())\n    }\n};","handlingStrategy":"fallback","validationCode":"// before finalize_transit\nlet hits = map.boundary_polygon.get_outer_ring().all_intersections(&route.shape);\nif hits.is_empty() {\n    warn!(\"route {} shape never touches the boundary\", route.route_id);\n}","typeGuard":null,"tryCatchPattern":"match create_route(...) { Err(e) if e.to_string().contains(\"shape enters map\") => { warn!(\"skipping contained route: {}\", e); continue; }, r => r }","preventionTips":["Use one consistent projection for GTFS shapes and the map boundary","Extrapolate shapes slightly beyond the boundary before intersecting","Sanity-check boundary polygon simplification","Report skipped routes so feed data quality issues surface"],"tags":["gis","transit","gtfs","geometry"],"backgroundTag":"empty-result-set","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"}