zeroclaw-labs/zeroclaw · error

wttr.in returned HTTP {status} for location '{location}'. Ch

Error message

wttr.in returned HTTP {status} for location '{location}'. Check that the location is valid.

What it means

The weather tool calls wttr.in (a free, keyless service) with ?format=j1 and requires a 2xx status; any non-success response bails with the HTTP status and the requested location. wttr.in most commonly returns 404 for unresolvable locations and 503/504 when the service is overloaded or rate-limiting.

Source

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

    /// Fetch and parse the wttr.in JSON response.
    async fn fetch(location: &str) -> anyhow::Result<WttrResponse> {
        let url = Self::build_url(location);

        let builder = reqwest::Client::builder()
            .timeout(Duration::from_secs(WTTR_TIMEOUT_SECS))
            .connect_timeout(Duration::from_secs(WTTR_CONNECT_TIMEOUT_SECS))
            .user_agent("zeroclaw-weather/1.0");

        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,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Verify the location string resolves (try it in a browser at wttr.in/<location>) and correct spelling/format
  2. Retry with exponential backoff and jitter — 5xx and rate-limit responses are transient
  3. Reduce polling frequency or cache responses; wttr.in data changes at most hourly
  4. If the outage persists, wait or switch location format (city, IATA code like JFK, 'lat,lon', or zip)

Example fix

// before
{"location":"San Francisko"}  // wttr.in returned HTTP 404
// after
{"location":"San Francisco"}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check the location resolves cheaply before polling
// (format guidance: city, IATA code, "lat,lon", zip)
fn plausible_location(loc: &str) -> bool {
    !loc.trim().is_empty() && loc.len() < 64
}

Try / catch

Err(e) if e.to_string().starts_with("wttr.in returned HTTP") => {
    if e.to_string().contains("404") { /* fix location, no retry */ }
    else { backoff_and_retry().await /* 5xx/429 are transient */ }
}

Prevention

When it happens

Trigger: A misspelled or invented city name (404); sustained polling that trips wttr.in's informal rate limits (429/503); transient outages of the public service (500/502/503/504).

Common situations: Agents polling weather on a schedule; bursts of requests when many sessions start at once (e.g. morning cron storms); a typo like "San Francisko" producing 404 rather than an empty result.

Related errors


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