a-b-street/abstreet · error
Traffic signal does not allow enough time in stage to…
Error message
Traffic signal does not allow enough time in stage to complete the crosswalk
Stage Index{}
Stage : {:?}
Time Required: {}
Time Given: {} What it means
TrafficSignal::validate ensures each stage's duration is at least the minimum time a pedestrian needs to finish crossing any crosswalk in that stage. If the stage's simple_duration is shorter than get_min_crossing_time for the stage, the signal would strand pedestrians mid-crossing, so import bails.
Solutions
- Increase the stage's Fixed duration to at least get_min_crossing_time for that stage index
- Shorten or reroute the crosswalk, or move the crosswalk's protected time to a longer stage
- Use adjust_major_minor_timing or another helper that respects minimum crossing times instead of raw duration edits
- Compute and print min crossing times per stage before tuning durations
Example fix
// before stage.stage_type = StageType::Fixed(Duration::seconds(5)); // after let min_time = signal.get_min_crossing_time(stage_idx, intersection); stage.stage_type = StageType::Fixed(min_time.max(Duration::seconds(5)));
Defensive patterns
Strategy: validation
Validate before calling
let need = signal.get_min_crossing_time(idx, i);
if stage.stage_type.simple_duration() < need {
stage.stage_type = StageType::Fixed(need);
} Type guard
fn duration_safe(stage: &Stage, idx: usize, i: &Intersection) -> bool {
stage.stage_type.simple_duration() >= /* need access via signal */ true
} Try / catch
match signal.adjust_stage_duration(idx, new_time, i) {
Err(e) => eprintln!("raise duration or shorten crosswalk: {e}"),
Ok(_) => {}
} Prevention
- Clamp every stage duration to at least the stage's min crossing time before assigning
- Compute crossing times for wide crossings before shortening cycle times
- Never hand-set Fixed durations below computed pedestrian requirements
When it happens
Trigger: Setting a StageType::Fixed duration below the computed pedestrian crossing time for the stage's crosswalks (long/wide crossings, or very short stage times); affecting pedestrian and unprotected turn movements in the stage.
Common situations: Aggressively shortening cycle times to reduce car delay; importing maps where crosswalks span very wide roads; tuning signal timings by hand without checking walk times.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Traffic signal assignment for
- Traffic signal has conflicting protected movements in one…
- CityName::new( , ) has a country code that isn't two letters
- must_get_sidewalk broken by
- Dropdown has default_value , but none of the choices match…
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/a0e9dde50f4aa8e2.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/objects/traffic_signals.rs:130
bail!(
"Traffic signal has conflicting protected movements in one \
stage:\n{:?}\n\n{:?}",
m1,
m2
);
}
}
}
// Do any of the crosswalks yield?
for m in stage.yield_movements.iter().map(|m| &i.movements[m]) {
// TODO Maybe make UnmarkedCrossing yield
assert!(!m.turn_type.pedestrian_crossing())
}
// Is there enough time in each stage to walk across the crosswalk
let min_crossing_time = self.get_min_crossing_time(stage_index, i);
if stage.stage_type.simple_duration() < min_crossing_time {
bail!(
"Traffic signal does not allow enough time in stage to complete the \
crosswalk\nStage Index{}\nStage : {:?}\nTime Required: {}\nTime Given: {}",
stage_index,
stage,
min_crossing_time,
stage.stage_type.simple_duration()
);
}
}
Ok(())
}
/// Move crosswalks from stages, adding them to an all-walk as last stage. This may promote
/// yields to protected. True is returned if any stages were added or modified.
pub fn convert_to_ped_scramble(&mut self, i: &Intersection) -> bool {
self.internal_convert_to_ped_scramble(true, i)
}
/// Move crosswalks from stages, adding them to an all-walk as last stage. This does not promoteView on GitHub (pinned to 0964f29315)