{"record":{"id":"6b76197976600af9","repo":"a-b-street/abstreet","slug":"can-t-start-at-it-s-the-edge-of-a-border-already","errorCode":null,"errorMessage":"Can't start at {}; it's the edge of a border already","messagePattern":"Can't start at (.+?); it's the edge of a border already","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sim/src/make/spawner.rs","lineNumber":78,"sourceCode":"impl TripSpec {\n    pub fn into_plan(self, map: &Map) -> (TripSpec, Vec<TripLeg>) {\n        // TODO We'll want to repeat this validation when we spawn stuff later for a second leg...\n        let mut legs = Vec::new();\n        match &self {\n            TripSpec::VehicleAppearing {\n                start_pos,\n                goal,\n                use_vehicle,\n                ..\n            } => {\n                if start_pos.dist_along() >= map.get_l(start_pos.lane()).length() {\n                    panic!(\"Can't spawn at {}; it isn't that long\", start_pos);\n                }\n                if let DrivingGoal::Border(_, end_lane) = goal {\n                    if start_pos.lane() == *end_lane\n                        && start_pos.dist_along() == map.get_l(*end_lane).length()\n                    {\n                        panic!(\n                            \"Can't start at {}; it's the edge of a border already\",\n                            start_pos\n                        );\n                    }\n                }\n\n                let constraints = if use_vehicle.vehicle_type == VehicleType::Bike {\n                    PathConstraints::Bike\n                } else {\n                    PathConstraints::Car\n                };\n\n                legs.push(TripLeg::Drive(*use_vehicle, goal.clone()));\n                if let DrivingGoal::ParkNear(b) = goal {\n                    legs.push(TripLeg::Walk(SidewalkSpot::building(*b, map)));\n                }\n\n                if goal.goal_pos(constraints, map).is_none() {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/sim/src/make/spawner.rs#L60-L96","documentation":"A spawn whose start position is exactly at the end of its goal border lane means the trip is already finished at distance zero. into_plan treats this degenerate trip (start == end at a border edge) as a specification bug and panics.","triggerScenarios":"into_plan() with a DrivingGoal::Border whose end_lane equals start_pos.lane() and start_pos.dist_along() equals that lane's full length — the agent spawns at the very border it aims to reach.","commonSituations":"Scenario generators sampling spawn positions uniformly along a border lane and hitting exactly lane end; agents intended to enter the map that are instead placed on the exit border.","solutions":["Nudge the spawn dist_along back from the lane end (spawn strictly inside the map)","Reject or resample such spawns in the scenario generator","Choose a different border/lane as the trip goal"],"exampleFix":"// before\nlet start = Position::new(border_lane, lane_length);\n// after\nlet start = Position::new(border_lane, lane_length - Distance::meters(1.0));","handlingStrategy":"validation","validationCode":"if let DrivingGoal::Border(_, end_lane) = goal {\n    if start_pos.lane() == *end_lane\n        && start_pos.dist_along() == map.get_l(*end_lane).length()\n    {\n        return None; // degenerate trip\n    }\n}","typeGuard":null,"tryCatchPattern":"let plan = std::panic::catch_unwind(|| spec.into_plan(&map, &mut rng));","preventionTips":["Spawn strictly inside the map, never at the border lane end","Filter degenerate (start==goal) trips when generating scenarios"],"tags":["rust","panic","invalid-state-transition","simulation"],"backgroundTag":"invalid-argument-value","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"}