a-b-street/abstreet · error
Unknown mode
Error message
Unknown mode {} What it means
get_mode maps the Soundcast trip file's mode column codes to a TripMode (Drive for 3.0-5.0, Transit for 6.0-8.0, Walk for 0.0, etc.). Any unrecognized mode string panics with "Unknown mode {code}" during scenario import. Strictness is deliberate so unknown modal codes aren't silently miscategorized.
Solutions
- Look up the offending mode code in the psrc/soundcast wiki (_trip.tsv docs) and either fix the data or add a mapping arm.
- Default unknown codes to TripMode::Walk (as already done for the invalid "0.0" code) instead of panicking, if approximate mapping is acceptable.
- Pre-validate the trip file's mode column against the known set before running the import.
- Regenerate inputs with the matching Soundcast model version.
Example fix
// before
_ => panic!("Unknown mode {}", code),
// after
other => {
warn!("Unknown mode {}, treating as walk", other);
TripMode::Walk
} Defensive patterns
Strategy: validation
Validate before calling
const KNOWN_MODES: [&str; 9] = ["0.0","1.0","2.0","3.0","4.0","5.0","6.0","7.0","8.0"];
let bad: Vec<_> = rows.iter().filter(|r| !KNOWN_MODES.contains(&r.mode.as_str())).collect();
assert!(bad.is_empty(), "unknown mode values: {:?}", bad); Type guard
fn is_known_mode(code: &str) -> bool {
matches!(code, "0.0"|"1.0"|"2.0"|"3.0"|"4.0"|"5.0"|"6.0"|"7.0"|"8.0")
} Try / catch
// Panics uncatchably; coerce before import:
let mode = if is_known_mode(raw) { raw } else { "0.0".to_string() }; Prevention
- Cross-check mode codes against the psrc/soundcast wiki for your model version.
- Pre-scan the mode column and report distinct unknown values in bulk.
- Keep trip inputs from the same Soundcast run as other population files.
When it happens
Trigger: Calling import_trips on a _trip.tsv whose mode column contains a value outside the mapped set (e.g. "9.0", "NA", blank, or codes from a different model version).
Common situations: Newer PSRC Soundcast releases adding mode categories; malformed TSV rows; using trip files from a different regional model with different coding; hand-edited input data.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unknown dpurp
- Some IndividTrip wasn't associated with a Person?!
- This build of A/B Street stores player data in…
- Can't find the data/ directory
- CityName::new( , ) has a country code that isn't two letters
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/a31103179602ace7.
Report an issue: GitHub.
Appendix: source
Thrown at importer/src/soundcast/popdat.rs:265
"8.0" => TripPurpose::Recreation,
"9.0" => TripPurpose::Medical,
"10.0" => TripPurpose::ParkAndRideTransfer,
_ => panic!("Unknown dpurp {}", code),
}
}
// From https://github.com/psrc/soundcast/wiki/Outputs#trip-file-_triptsv, mode
fn get_mode(code: &str) -> TripMode {
match code {
"1.0" => TripMode::Walk,
"2.0" => TripMode::Bike,
"3.0" | "4.0" | "5.0" => TripMode::Drive,
// TODO Park-and-ride and school bus as walk-to-transit is a little weird.
"6.0" | "7.0" | "8.0" => TripMode::Transit,
// TODO Invalid code, what's this one mean? I only see a few examples, so just default to
// walking.
"0.0" => TripMode::Walk,
_ => panic!("Unknown mode {}", code),
}
}
// See https://github.com/psrc/soundcast/wiki/Outputs#trip-file-_triptsv
//
// A/B Street flattens a person's trips into a simple list, but the Soundcast model is more
// detailed:
//
// A person takes 1+ tours a day. Each tour starts and ends at the same place (usually home) and
// has some primary destination. A tour has two legs (to the destination, then returning from it),
// each split into individual trips.
//
// An example: someone takes the bus to work, but stops for a coffee and walks the final bit to
// work. Then later they bus home. This would be encoded like so:
//
// - Tour 1 (purpose work), leg = to destination, trip 1 (purpose eat, using transit)
// - Tour 1 (purpose work), leg = to destination, trip 2 (purpose work, walking)
// - Tour 1 (purpose work), leg = return from destination, trip 1 (purpose home, using transit)View on GitHub (pinned to 0964f29315)