a-b-street/abstreet · error
{}
Error message
{} What it means
When building a ControlTrafficSignal during map import, the signal plan's stage/error messages are accumulated in an `errors` vector; if the plan failed to parse into valid stages, the importer bails with all collected errors joined by "; ". The empty `{}` placeholder is just the joined error list, so the real diagnostics are inside the message. This is a pre-validation gate before a signal is ever constructed, so a thrown signal plan is rejected at import time rather than producing a broken simulation object.
Solutions
- Read the joined messages after the `; ` separators; each is a specific stage validation failure to fix individually.
- Correct the offending stage definitions in the signal plan file (durations, movements) and re-run import.
- Regenerate the signal plan from the original map source or a matching map version instead of hand-editing.
- If converting maps between formats, ensure the converter emits stages matching the current map_model schema.
Example fix
// before (invalid stage in signal JSON)
{"stages": [{"type": "unknown"}]}
// after
{"stages": [{"type": "protected", "protected": ["north_south"], "duration": 5.0}]} Defensive patterns
Strategy: validation
Validate before calling
if let Some(errs) = validate_signal_plan(&plan_json) {
eprintln!("invalid signal plan: {}", errs.join("; "));
return Err(...);
}
// only import when validate_signal_plan returns empty Try / catch
match import_map(...) {
Err(e) if e.to_string().contains(';') => {
for msg in e.to_string().split("; ") { eprintln!("- {}", msg); }
}
Err(e) => return Err(e),
Ok(m) => m,
} Prevention
- Validate signal plan JSON against the current map_model schema before import.
- Never hand-edit signal files; regenerate them from the map source.
- Import maps in CI so signal-plan breakage is caught immediately.
When it happens
Trigger: Importing a map (import pipeline) whose traffic-signal plan (e.g. from a .signal JSON) contains one or more invalid stage definitions; every failing check pushes into `errors` and, once any exist, `bail!("{}", errors.join("; "))` fires at map_model/src/objects/traffic_signals.rs:457.
Common situations: Hand-edited or exported signal plans with malformed stage durations, missing movements, or mismatched intersection geometry; maps converted from other formats where signal data was imperfectly translated.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Traffic signal assignment for
- Some trip has negative departure time
- CityName::new( , ) has a country code that isn't two letters
- Dropdown has default_value , but none of the choices match…
- Bad CityName
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/4b100c3d154d99b0.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/objects/traffic_signals.rs:457
if errors.is_empty() {
stages.push(Stage {
protected_movements,
yield_movements: permitted_movements,
stage_type: match s.stage_type {
perma_traffic_signal::StageType::Fixed(d) => {
StageType::Fixed(Duration::seconds(d as f64))
}
perma_traffic_signal::StageType::Variable(min, delay, additional) => {
StageType::Variable(
Duration::seconds(min as f64),
Duration::seconds(delay as f64),
Duration::seconds(additional as f64),
)
}
},
});
} else {
bail!("{}", errors.join("; "));
}
}
let ts = ControlTrafficSignal {
id,
stages,
offset: Duration::seconds(plan.offset_seconds as f64),
};
ts.validate(map.get_i(id))?;
Ok(ts)
}
}
View on GitHub (pinned to 0964f29315)