a-b-street/abstreet · error · anyhow::Error

missing GET parameter

Error message

missing GET parameter {}

What it means

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.

Solutions

  1. Include all required query parameters for the endpoint (check the match arms in handle_command for names)
  2. Fix typos/case in parameter names
  3. Update the client to the current headless API contract
  4. Encode parameters properly (percent-encode values like GPS points)

Example fix

// before
curl 'http://localhost:1234/geo/roads'
// after
curl 'http://localhost:1234/geo/roads?pt=47.6,-122.3&threshold_meters=50'
Defensive patterns

Strategy: validation

Validate before calling

// client-side check before sending
const required = ['pt', 'threshold_meters'];
for (const k of required) {
  if (!(k in params)) throw new Error(`missing GET parameter ${k}`);
}

Try / catch

let resp = fetch(url).await?;
if !resp.status().is_success() {
    let body = resp.text().await?;
    if body.contains("missing GET parameter") { /* fix params and retry */ }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/4e143d9dc616f446. Report an issue: GitHub.

Appendix: source

Thrown at headless/src/main.rs:151

                    .body(Body::from(format!("Bad command {}: {}", path, err)))
                    .unwrap()
            }
        },
    )
}

fn handle_command(
    path: &str,
    params: &HashMap<String, String>,
    body: &[u8],
    sim: &mut Sim,
    map: &mut Map,
    load: &mut LoadSim,
) -> Result<String> {
    let get = |key: &str| {
        params
            .get(key)
            .ok_or_else(|| anyhow!("missing GET parameter {}", key))
    };

    match path {
        // Controlling the simulation
        "/sim/reset" => {
            let (new_map, new_sim) = load.setup(&mut Timer::new("reset sim"));
            *map = new_map;
            *sim = new_sim;
            Ok("sim reloaded".to_string())
        }
        "/sim/load" => {
            let args: LoadSim = abstutil::from_json(body)?;

            load.scenario = args.scenario;
            load.modifiers = args.modifiers;
            load.edits = args.edits;

            // Also reset

View on GitHub (pinned to 0964f29315)