{"record":{"id":"4b100c3d154d99b0","repo":"a-b-street/abstreet","slug":"traffic-signals","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/objects/traffic_signals.rs","lineNumber":457,"sourceCode":"            if errors.is_empty() {\n                stages.push(Stage {\n                    protected_movements,\n                    yield_movements: permitted_movements,\n                    stage_type: match s.stage_type {\n                        perma_traffic_signal::StageType::Fixed(d) => {\n                            StageType::Fixed(Duration::seconds(d as f64))\n                        }\n                        perma_traffic_signal::StageType::Variable(min, delay, additional) => {\n                            StageType::Variable(\n                                Duration::seconds(min as f64),\n                                Duration::seconds(delay as f64),\n                                Duration::seconds(additional as f64),\n                            )\n                        }\n                    },\n                });\n            } else {\n                bail!(\"{}\", errors.join(\"; \"));\n            }\n        }\n        let ts = ControlTrafficSignal {\n            id,\n            stages,\n            offset: Duration::seconds(plan.offset_seconds as f64),\n        };\n        ts.validate(map.get_i(id))?;\n        Ok(ts)\n    }\n}\n","sourceCodeStart":439,"sourceCodeEnd":469,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/objects/traffic_signals.rs#L439-L469","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (invalid stage in signal JSON)\n{\"stages\": [{\"type\": \"unknown\"}]}\n// after\n{\"stages\": [{\"type\": \"protected\", \"protected\": [\"north_south\"], \"duration\": 5.0}]}","handlingStrategy":"validation","validationCode":"if let Some(errs) = validate_signal_plan(&plan_json) {\n    eprintln!(\"invalid signal plan: {}\", errs.join(\"; \"));\n    return Err(...);\n}\n// only import when validate_signal_plan returns empty","typeGuard":null,"tryCatchPattern":"match import_map(...) {\n    Err(e) if e.to_string().contains(';') => {\n        for msg in e.to_string().split(\"; \") { eprintln!(\"- {}\", msg); }\n    }\n    Err(e) => return Err(e),\n    Ok(m) => m,\n}","preventionTips":["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."],"tags":["import","traffic-signal","map-model","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}