a-b-street/abstreet · error · anyhow::Error

Person ( ) has no trips at all

Error message

Person ({:?}) has no trips at all

What it means

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.

Solutions

  1. Filter out individuals with no trips before building the scenario
  2. Ensure the import/generation pipeline produces at least one trip per person
  3. Give such people a stay-at-home or idle trip pattern

Example fix

// before
specs.push(person_spec);
// after
if !person_spec.trips.is_empty() { specs.push(person_spec); }
Defensive patterns

Strategy: validation

Validate before calling

if person.trips.is_empty() {
    eprintln!("dropping person {} with no trips", person.orig_id);
} else {
    specs.push(person);
}

Type guard

fn has_trips(p: &PersonSpec) -> bool { !p.trips.is_empty() }

Try / catch

match person.check_schedule() {
    Ok(()) => scenario_people.push(person),
    Err(e) if e.to_string().contains("no trips") => {}, // drop
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: Imported data where all trips for an individual were dropped by preprocessing, population generators that emit placeholders for people with no modeled activity.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/6830e5eba0d0307e. Report an issue: GitHub.

Appendix: source

Thrown at synthpop/src/scenario.rs:168

            return "weekday".to_string();
        }
        if name.city.country == "gb" {
            for x in ["background", "base_with_bg"] {
                if abstio::file_exists(abstio::path_scenario(name, x)) {
                    return x.to_string();
                }
            }
        }
        // Dynamically generated -- arguably this is an absence of a default scenario
        "home_to_work".to_string()
    }
}

impl PersonSpec {
    /// Verify that a person's trips make sense
    pub fn check_schedule(&self) -> Result<()> {
        if self.trips.is_empty() {
            bail!("Person ({:?}) has no trips at all", self.orig_id);
        }

        for pair in self.trips.windows(2) {
            if pair[0].depart >= pair[1].depart {
                bail!(
                    "Person ({:?}) starts two trips in the wrong order: {} then {}",
                    self.orig_id,
                    pair[0].depart,
                    pair[1].depart
                );
            }

            if pair[0].destination != pair[1].origin {
                // Exiting one border and re-entering another is fine
                if matches!(pair[0].destination, TripEndpoint::Border(_))
                    && matches!(pair[1].origin, TripEndpoint::Border(_))
                {
                    continue;

View on GitHub (pinned to 0964f29315)