a-b-street/abstreet · error
This intersection doesn't use fixed timing.
Error message
This intersection doesn't use fixed timing.
What it means
adjust_major_minor_timing only rewrites StageType::Fixed stages. If any stage uses a different StageType (e.g. adaptive/variable timing), the method bails rather than silently overwriting a non-fixed timing policy.
Solutions
- Convert all stages to StageType::Fixed before calling adjust_major_minor_timing
- Skip signals using non-fixed timing, or use the appropriate API for that timing type
- Recreate the signal assignment with default fixed stages
- Persist/restore fixed timing before applying major/minor durations
Example fix
// before
signal.adjust_major_minor_timing(major, minor, map)?;
// after
if signal.stages.iter().all(|s| matches!(s.stage_type, StageType::Fixed(_))) {
signal.adjust_major_minor_timing(major, minor, map)?;
} Defensive patterns
Strategy: validation
Validate before calling
if !signal.stages.iter().all(|s| matches!(s.stage_type, StageType::Fixed(_))) {
return Err(anyhow!("signal {} uses non-fixed timing", signal.id));
} Type guard
fn all_fixed(signal: &TrafficSignal) -> bool {
signal.stages.iter().all(|s| matches!(s.stage_type, StageType::Fixed(_)))
} Try / catch
if all_fixed(signal) {
signal.adjust_major_minor_timing(major, minor, map)?;
} else {
skip_non_fixed(signal.id);
} Prevention
- Convert stages to StageType::Fixed before fixed-duration retiming
- Track which signals use adaptive timing and route them to the right API
- Avoid mixing timing policies on the same signal
When it happens
Trigger: Calling adjust_major_minor_timing on a signal whose stages include a non-Fixed StageType variant, encountered in the loop over self.stages before any duration is modified.
Common situations: Signals loaded from a scenario or edited with adaptive timing; mixing timing plugins/experiments with the fixed major/minor retiming helper.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- This intersection doesn't have 2 stages.
- This intersection doesn't have major/minor roads; they're…
- This intersection didn't already group major/minor roads…
- isn't a traffic signal
- Traffic signal assignment for
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/20ca05f0682c965d.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/objects/traffic_signals.rs:236
// What's the rank of each road?
let mut rank_per_road: BTreeMap<RoadID, usize> = BTreeMap::new();
for r in &map.get_i(self.id).roads {
rank_per_road.insert(*r, map.get_r(*r).get_detailed_rank());
}
let mut ranks: Vec<usize> = rank_per_road.values().cloned().collect();
ranks.sort_unstable();
ranks.dedup();
if ranks.len() == 1 {
bail!("This intersection doesn't have major/minor roads; they're all the same rank.");
}
let highest_rank = ranks.pop().unwrap();
// Try to apply the transformation
let orig = self.clone();
for stage in &mut self.stages {
match stage.stage_type {
StageType::Fixed(_) => {}
_ => bail!("This intersection doesn't use fixed timing."),
}
// Ignoring crosswalks, do any of the turns come from a major road?
if stage
.protected_movements
.iter()
.any(|m| !m.crosswalk && highest_rank == rank_per_road[&m.from.road])
{
stage.stage_type = StageType::Fixed(major);
} else {
stage.stage_type = StageType::Fixed(minor);
}
}
if self.simple_cycle_duration() != major + minor {
bail!("This intersection didn't already group major/minor roads together.");
}
if self == &orig {View on GitHub (pinned to 0964f29315)