{"record":{"id":"4e143d9dc616f446","repo":"a-b-street/abstreet","slug":"missing-get-parameter","errorCode":null,"errorMessage":"missing GET parameter {}","messagePattern":"missing GET parameter (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"headless/src/main.rs","lineNumber":151,"sourceCode":"                    .body(Body::from(format!(\"Bad command {}: {}\", path, err)))\n                    .unwrap()\n            }\n        },\n    )\n}\n\nfn handle_command(\n    path: &str,\n    params: &HashMap<String, String>,\n    body: &[u8],\n    sim: &mut Sim,\n    map: &mut Map,\n    load: &mut LoadSim,\n) -> Result<String> {\n    let get = |key: &str| {\n        params\n            .get(key)\n            .ok_or_else(|| anyhow!(\"missing GET parameter {}\", key))\n    };\n\n    match path {\n        // Controlling the simulation\n        \"/sim/reset\" => {\n            let (new_map, new_sim) = load.setup(&mut Timer::new(\"reset sim\"));\n            *map = new_map;\n            *sim = new_sim;\n            Ok(\"sim reloaded\".to_string())\n        }\n        \"/sim/load\" => {\n            let args: LoadSim = abstutil::from_json(body)?;\n\n            load.scenario = args.scenario;\n            load.modifiers = args.modifiers;\n            load.edits = args.edits;\n\n            // Also reset","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/headless/src/main.rs#L133-L169","documentation":"The headless HTTP server's handle_command uses a local closure get(key) that looks up a query-string parameter and returns anyhow!(\"missing GET parameter {}\") when absent. Every API path validates its required query parameters through this closure, so this error signals a malformed request to the API.","triggerScenarios":"Sending an HTTP request to /sim/*, /map/*, or other endpoints without a required query parameter, e.g. GET /geo/roads?... omitting pt=..., or misspelling a parameter name.","commonSituations":"Hand-crafted curl requests missing params; client code and server API out of sync; typos in parameter names (case-sensitive); URL-encoded params lost by an intermediary.","solutions":["Include all required query parameters for the endpoint (check the match arms in handle_command for names)","Fix typos/case in parameter names","Update the client to the current headless API contract","Encode parameters properly (percent-encode values like GPS points)"],"exampleFix":"// before\ncurl 'http://localhost:1234/geo/roads'\n// after\ncurl 'http://localhost:1234/geo/roads?pt=47.6,-122.3&threshold_meters=50'","handlingStrategy":"validation","validationCode":"// client-side check before sending\nconst required = ['pt', 'threshold_meters'];\nfor (const k of required) {\n  if (!(k in params)) throw new Error(`missing GET parameter ${k}`);\n}","typeGuard":null,"tryCatchPattern":"let resp = fetch(url).await?;\nif !resp.status().is_success() {\n    let body = resp.text().await?;\n    if body.contains(\"missing GET parameter\") { /* fix params and retry */ }\n}","preventionTips":["Keep a documented list of required query params per endpoint","Encode parameter values (GPS points, strings) with percent-encoding","Match client param names exactly (case-sensitive) to the server"],"tags":["http","api","query-params","validation"],"backgroundTag":"invalid-query-parameter","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"}