{"record":{"id":"82f2d2725f466aee","repo":"a-b-street/abstreet","slug":"isn-t-a-traffic-signal","errorCode":null,"errorMessage":"{} isn't a traffic signal","messagePattern":"(.+?) isn't a traffic signal","errorType":"http","errorClass":null,"httpStatus":404,"severity":"error","filePath":"headless/src/main.rs","lineNumber":220,"sourceCode":"                }\n            }\n\n            let mut scenario = Scenario::empty(map, \"one-shot\");\n            scenario.people = ExternalPerson::import(map, vec![input], false)?;\n            let mut rng = XorShiftRng::seed_from_u64(load.rng_seed);\n            sim.instantiate(&scenario, map, &mut rng, &mut Timer::throwaway());\n            Ok(format!(\n                \"{} created\",\n                sim.get_all_people().last().unwrap().id\n            ))\n        }\n        // Traffic signals\n        \"/traffic-signals/get\" => {\n            let i = IntersectionID(get(\"id\")?.parse::<usize>()?);\n            if let Some(ts) = map.maybe_get_traffic_signal(i) {\n                Ok(abstutil::to_json(ts))\n            } else {\n                bail!(\"{} isn't a traffic signal\", i)\n            }\n        }\n        \"/traffic-signals/set\" => {\n            let ts: ControlTrafficSignal = abstutil::from_json(body)?;\n            let id = ts.id;\n\n            // incremental_edit_traffic_signal is the cheap option, but since we may need to call\n            // get-edits later, go through the proper flow.\n            let mut edits = map.get_edits().clone();\n            edits.commands.push(map.edit_intersection_cmd(id, |new| {\n                new.control = EditIntersectionControl::TrafficSignal(ts.export(map));\n            }));\n            map.must_apply_edits(edits, &mut Timer::throwaway());\n            map.recalculate_pathfinding_after_edits(&mut Timer::throwaway());\n\n            Ok(format!(\"{} has been updated\", id))\n        }\n        \"/traffic-signals/get-delays\" => {","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/headless/src/main.rs#L202-L238","documentation":"The /traffic-signals/get command looks up an intersection and returns its ControlTrafficSignal state. Only intersections actually controlled by a traffic signal exist in the signals map; if the given IntersectionID is an stop sign, border, or uncontrolled intersection, the library bails with this error.","triggerScenarios":"POST /traffic-signals/get with id=<usize> where maybe_get_traffic_signal(IntersectionID(id)) returns None — the intersection exists but isn't signalized.","commonSituations":"Iterating all intersection IDs instead of only traffic-signal IDs; map re-imports that changed an intersection's control type; hardcoded IDs from a different map.","solutions":["Verify the intersection is a traffic signal (i.is_traffic_signal()) before querying; enumerate map.all_lts / signal IDs instead of guessing.","Get the ID from the map itself (e.g. by filtering intersections whose control is a signal) rather than hardcoding.","Refresh your ID references after re-importing the map, since control types can change between imports."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// enumerate only signalized intersections from the map first\nconst signalIds = map.intersections.filter(i => i.is_traffic_signal()).map(i => i.id);","typeGuard":"function isTrafficSignal(i) { return i.control === \"TrafficSignal\"; }","tryCatchPattern":"try {\n  ts = await post(\"/traffic-signals/get\", { id });\n} catch (e) {\n  if (String(e).includes(\"isn't a traffic signal\")) ts = null;\n}","preventionTips":["Only query intersections known to be traffic signals","Refresh intersection IDs after map re-imports","Don't assume control types persist across imports"],"tags":["traffic-signals","http-api","lookup"],"backgroundTag":"resource-not-found","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"}