a-b-street/abstreet · error
It's now, so you can't start a trip at
Error message
It's {} now, so you can't start a trip at {} What it means
The /sim/new-person command validates that every trip's departure time is not before the current simulation time; the simulation can't spawn a trip in the past. It rejects the whole request if any trip departs before sim.time().
Solutions
- Clamp or shift trip departure times to be >= the current /sim/get-time value before submitting.
- Reset the simulation (/sim/reset) so time returns to 0 and original departures are valid again.
- Ensure your scenario generator and the sim use the same time units/format for departure.
Example fix
// before
await post("/sim/new-person", person); // departures from t=0 schedule
// after
const now = parseTime(await post("/sim/get-time"));
person.trips.forEach(t => { if (t.departure < now) t.departure = now; });
await post("/sim/new-person", person); Defensive patterns
Strategy: validation
Validate before calling
const now = parseTime(await post("/sim/get-time"));
if (person.trips.some(t => parseTime(t.departure) < now)) throw new Error("trip departure is in the past"); Try / catch
try {
await post("/sim/new-person", person);
} catch (e) {
if (String(e).includes("can't start a trip at")) {
const now = await post("/sim/get-time");
person.trips.forEach(t => { if (t.departure < now) t.departure = now; });
await post("/sim/new-person", person);
}
} Prevention
- Clamp departures to current sim time before submission
- Reset the sim before replaying recorded schedules
- Use consistent time formats between generator and sim
When it happens
Trigger: POST /sim/new-person with an ExternalPerson JSON body where at least one trip.departure < sim.time() (e.g. after the simulation has already advanced).
Common situations: Replaying trip schedules recorded at time 0 after the sim has run for a while; hardcoded departure times in test scripts; clock drift between scenario generator and sim time (times in different formats/offsets).
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
- is in the past. call /sim/reset first?
- Bad TimeInterval ..
- Bad DistanceInterval
- Can't spawn at ; it isn't that long
- Can't start at ; it's the edge of a border already
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/30d6dac67c5430c4.
Report an issue: GitHub.
Appendix: source
Thrown at headless/src/main.rs:197
*sim = Sim::new(&map, SimOptions::default());
Ok("map changed, blank simulation".to_string())
}
"/sim/get-time" => Ok(sim.time().to_string()),
"/sim/goto-time" => {
let t = Time::parse(get("t")?)?;
if t <= sim.time() {
bail!("{} is in the past. call /sim/reset first?", t)
} else {
let dt = t - sim.time();
sim.timed_step(map, dt, &mut None, &mut Timer::new("goto-time"));
Ok(format!("it's now {}", t))
}
}
"/sim/new-person" => {
let input: ExternalPerson = abstutil::from_json(body)?;
for trip in &input.trips {
if trip.departure < sim.time() {
bail!(
"It's {} now, so you can't start a trip at {}",
sim.time(),
trip.departure
)
}
}
let mut scenario = Scenario::empty(map, "one-shot");
scenario.people = ExternalPerson::import(map, vec![input], false)?;
let mut rng = XorShiftRng::seed_from_u64(load.rng_seed);
sim.instantiate(&scenario, map, &mut rng, &mut Timer::throwaway());
Ok(format!(
"{} created",
sim.get_all_people().last().unwrap().id
))
}
// Traffic signals
"/traffic-signals/get" => {View on GitHub (pinned to 0964f29315)