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

  1. Read the joined messages after the `; ` separators; each is a specific stage validation failure to fix individually.
  2. Correct the offending stage definitions in the signal plan file (durations, movements) and re-run import.
  3. Regenerate the signal plan from the original map source or a matching map version instead of hand-editing.
  4. 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

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


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)