{"record":{"id":"6830e5eba0d0307e","repo":"a-b-street/abstreet","slug":"person-has-no-trips-at-all","errorCode":null,"errorMessage":"Person ({:?}) has no trips at all","messagePattern":"Person \\((.+?)\\) has no trips at all","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"synthpop/src/scenario.rs","lineNumber":168,"sourceCode":"            return \"weekday\".to_string();\n        }\n        if name.city.country == \"gb\" {\n            for x in [\"background\", \"base_with_bg\"] {\n                if abstio::file_exists(abstio::path_scenario(name, x)) {\n                    return x.to_string();\n                }\n            }\n        }\n        // Dynamically generated -- arguably this is an absence of a default scenario\n        \"home_to_work\".to_string()\n    }\n}\n\nimpl PersonSpec {\n    /// Verify that a person's trips make sense\n    pub fn check_schedule(&self) -> Result<()> {\n        if self.trips.is_empty() {\n            bail!(\"Person ({:?}) has no trips at all\", self.orig_id);\n        }\n\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;","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/synthpop/src/scenario.rs#L150-L186","documentation":"PersonSpec::check_schedule validates a generated person's trip schedule before the scenario is finalized. If a person has zero trips, validation fails, because every person must do at least one thing during the day.","triggerScenarios":"Creating or importing a PersonSpec with an empty trips vector and then calling check_schedule, e.g. an external population whose individual has no trips after filtering.","commonSituations":"Imported data where all trips for an individual were dropped by preprocessing, population generators that emit placeholders for people with no modeled activity.","solutions":["Filter out individuals with no trips before building the scenario","Ensure the import/generation pipeline produces at least one trip per person","Give such people a stay-at-home or idle trip pattern"],"exampleFix":"// before\nspecs.push(person_spec);\n// after\nif !person_spec.trips.is_empty() { specs.push(person_spec); }","handlingStrategy":"validation","validationCode":"if person.trips.is_empty() {\n    eprintln!(\"dropping person {} with no trips\", person.orig_id);\n} else {\n    specs.push(person);\n}","typeGuard":"fn has_trips(p: &PersonSpec) -> bool { !p.trips.is_empty() }","tryCatchPattern":"match person.check_schedule() {\n    Ok(()) => scenario_people.push(person),\n    Err(e) if e.to_string().contains(\"no trips\") => {}, // drop\n    Err(e) => return Err(e),\n}","preventionTips":["Filter empty individuals in the import/generation pipeline","Always synthesize at least one trip per person","Run check_schedule early, before expensive scenario construction"],"tags":["synthpop","scenario","validation"],"backgroundTag":"empty-required-field","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"}