a-b-street/abstreet · error
Bad TimeInterval ..
Error message
Bad TimeInterval {} .. {} What it means
TimeInterval::new validates that the interval start precedes its end on the simulation time axis. If end < start the interval is meaningless (negative duration) so the library panics immediately rather than constructing a broken interval that would corrupt later percent()/duration math.
Solutions
- Swap the arguments so TimeInterval::new receives the earlier time first
- Sort or validate the source times before constructing the interval
- Debug-print the two Time values; if they come from user data, fix the producer
Example fix
// before let iv = TimeInterval::new(end, start); // after let iv = TimeInterval::new(start.min(end), start.max(end));
Defensive patterns
Strategy: validation
Validate before calling
fn safe_time_interval(start: Time, end: Time) -> Option<TimeInterval> {
if end < start { None } else { Some(TimeInterval::new(start, end)) }
} Type guard
fn valid_time_interval(start: Time, end: Time) -> bool { end >= start } Try / catch
let iv = std::panic::catch_unwind(|| TimeInterval::new(start, end)).ok();
Prevention
- Sort timestamps before building intervals
- Never pass raw unvalidated times from files directly to TimeInterval::new
When it happens
Trigger: Calling TimeInterval::new(start, end) with an end Time earlier than the start Time, e.g. by passing arguments in the wrong order or computing times from reversed data.
Common situations: Scenario files or CSV inputs where timestamps are swapped; deriving start/end from sorted-incorrect data; off-by-one when converting raw seconds; callers hand-building intervals for map UI slices.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Bad DistanceInterval
- Can't spawn at ; it isn't that long
- Can't start at ; it's the edge of a border already
- A trip just walking from
- trying to make a crossing_state from to at . Something's…
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/66281dda7fdf1620.
Report an issue: GitHub.
Appendix: source
Thrown at sim/src/lib.rs:505
assert!(pos.dist_along() <= lane.length());
SidewalkSpot {
sidewalk_pos: pos,
connection: SidewalkPOI::SuddenlyAppear,
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
pub(crate) struct TimeInterval {
// TODO Private fields
pub start: Time,
pub end: Time,
}
impl TimeInterval {
pub fn new(start: Time, end: Time) -> TimeInterval {
if end < start {
panic!("Bad TimeInterval {} .. {}", start, end);
}
TimeInterval { start, end }
}
pub fn percent(&self, t: Time) -> f64 {
if self.start == self.end {
return 1.0;
}
let x = (t - self.start) / (self.end - self.start);
assert!((0.0..=1.0).contains(&x));
x
}
pub fn percent_clamp_end(&self, t: Time) -> f64 {
if t > self.end {
return 1.0;
}View on GitHub (pinned to 0964f29315)