zeroclaw-labs/zeroclaw · warning

wttr.in could not resolve location '{location}'. Try a city

Error message

wttr.in could not resolve location '{location}'. Try a city name, airport code, GPS coordinates (lat,lon), or zip code.

What it means

wttr.in sometimes reports unknown locations with HTTP 200 but a plain-text body instead of JSON. The weather tool detects this by checking whether the body starts with '{' and bails with guidance on accepted location formats, since the JSON parse would otherwise produce a confusing error.

Source

Thrown at crates/zeroclaw-tools/src/weather_tool.rs:171

        let builder =
            zeroclaw_config::schema::apply_runtime_proxy_to_builder(builder, "tool.weather");
        let client = builder.build()?;

        let response = client.get(&url).send().await?;
        let status = response.status();

        if !status.is_success() {
            anyhow::bail!(
                "wttr.in returned HTTP {status} for location '{location}'. \
                 Check that the location is valid."
            );
        }

        let body = response.text().await?;

        // wttr.in returns a plain-text error string (not JSON) for unknown locations.
        if !body.trim_start().starts_with('{') {
            anyhow::bail!(
                "wttr.in could not resolve location '{location}'. \
                 Try a city name, airport code, GPS coordinates (lat,lon), or zip code."
            );
        }

        let parsed: WttrResponse = serde_json::from_str(&body).map_err(|e| {
            ::zeroclaw_log::record!(
                WARN,
                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
                    .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                    .with_attrs(::serde_json::json!({"error": format!("{}", e)})),
                "weather_tool: failed to parse wttr.in response"
            );
            anyhow::Error::msg(format!("Failed to parse wttr.in response: {e}"))
        })?;

        Ok(parsed)
    }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Use a recognized form: city name ("Paris"), IATA airport code ("LHR"), GPS as "lat,lon" ("48.85,2.35"), or a zip code ("94105")
  2. Validate/normalize user-supplied locations before calling the tool (spell-check or your own geocoder)
  3. On this error, fall back to a broader query like the containing city

Example fix

// before
{"location":"Main St 123 Springfield"}  // could not resolve
// after
{"location":"Springfield"}
Defensive patterns

Strategy: validation

Validate before calling

fn valid_wttr_location(loc: &str) -> bool {
    let l = loc.trim();
    !l.is_empty()
        && (l.chars().all(|c| c.is_alphanumeric() || c.is_whitespace() || c == "," || c == '-'))
        && !l.contains(";;")
}

Try / catch

Err(e) if e.to_string().starts_with("wttr.in could not resolve") => {
    // downgrade to a broader query (city only) or prompt the user; do not retry the same string
}

Prevention

When it happens

Trigger: Location strings like "xyzzy", made-up place names, malformed GPS ("48.85;2.35"), wrong-format zip codes, or IATA codes that are not airport codes; anything wttr.in cannot geocode but answers softly.

Common situations: Free-text user input passed straight to the tool (typos, business names, addresses); assuming any string is geocodable; using comma formats wttr.in does not accept.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/7f12636ae48bf2eb. Report an issue: GitHub.