{"record":{"id":"b89c965e77388d45","repo":"a-b-street/abstreet","slug":"person-warps-from-to-during-adjacent-trips","errorCode":null,"errorMessage":"Person ({:?}) warps from {:?} to {:?} during adjacent trips","messagePattern":"Person \\((.+?)\\) warps from (.+?) to (.+?) during adjacent trips","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"synthpop/src/scenario.rs","lineNumber":188,"sourceCode":"\n        for pair in self.trips.windows(2) {\n            if pair[0].depart >= pair[1].depart {\n                bail!(\n                    \"Person ({:?}) starts two trips in the wrong order: {} then {}\",\n                    self.orig_id,\n                    pair[0].depart,\n                    pair[1].depart\n                );\n            }\n\n            if pair[0].destination != pair[1].origin {\n                // Exiting one border and re-entering another is fine\n                if matches!(pair[0].destination, TripEndpoint::Border(_))\n                    && matches!(pair[1].origin, TripEndpoint::Border(_))\n                {\n                    continue;\n                }\n                bail!(\n                    \"Person ({:?}) warps from {:?} to {:?} during adjacent trips\",\n                    self.orig_id,\n                    pair[0].destination,\n                    pair[1].origin\n                );\n            }\n        }\n\n        for trip in &self.trips {\n            if trip.origin == trip.destination {\n                bail!(\n                    \"Person ({:?}) has a trip from/to the same place: {:?}\",\n                    self.orig_id,\n                    trip.origin\n                );\n            }\n        }\n","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/synthpop/src/scenario.rs#L170-L206","documentation":"check_schedule verifies trip continuity: each trip's destination must match the next trip's origin. If they differ (the person would teleport, or 'warp'), this error reports both endpoints. Re-entering the map through a Border endpoint is explicitly exempted.","triggerScenarios":"Adjacent trips where trip[n].destination != trip[n+1].origin and the endpoints are not both Border variants, e.g. data where intermediate movement is missing.","commonSituations":"Trip chains that omit a leg (e.g. dropped transit trips), imported populations with endpoint mismatches from deduplication, border-crossing logic differences between datasets.","solutions":["Repair the trip chain so each destination equals the next origin (insert the missing trip)","Insert a synthetic leg between the mismatched endpoints","Allow border-to-border transitions (already exempt) or normalize endpoints to Border when off-map"],"exampleFix":"// before\nlet trips = raw_trips; // destination != next origin\n// after\nlet trips = chain_trips(raw_trips); // inserts missing connecting legs","handlingStrategy":"validation","validationCode":"for pair in person.trips.windows(2) {\n    let ok = pair[0].destination == pair[1].origin\n        || (matches!(pair[0].destination, TripEndpoint::Border(_))\n            && matches!(pair[1].origin, TripEndpoint::Border(_)));\n    if !ok { return Err(anyhow!(\"trip chain discontinuity\")); }\n}","typeGuard":null,"tryCatchPattern":"match person.check_schedule() {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"warps\") => { person.trips = repair_chain(person.trips); }\n    Err(e) => return Err(e),\n}","preventionTips":["Insert connecting legs when chaining trips from separate data sources","Normalize off-map endpoints to Border so transitions are exempt","Validate continuity right after import, before scenario building"],"tags":["synthpop","scenario","validation"],"backgroundTag":"schema-validation-failed","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"}