{"record":{"id":"243246f8f6b6adc2","repo":"zeroclaw-labs/zeroclaw","slug":"wttr-in-returned-http-status-for-location-loca","errorCode":null,"errorMessage":"wttr.in returned HTTP {status} for location '{location}'. Check that the location is valid.","messagePattern":"wttr\\.in returned HTTP (.+?) for location '(.+?)'\\. Check that the location is valid\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/weather_tool.rs","lineNumber":161,"sourceCode":"\n    /// Fetch and parse the wttr.in JSON response.\n    async fn fetch(location: &str) -> anyhow::Result<WttrResponse> {\n        let url = Self::build_url(location);\n\n        let builder = reqwest::Client::builder()\n            .timeout(Duration::from_secs(WTTR_TIMEOUT_SECS))\n            .connect_timeout(Duration::from_secs(WTTR_CONNECT_TIMEOUT_SECS))\n            .user_agent(\"zeroclaw-weather/1.0\");\n\n        let builder =\n            zeroclaw_config::schema::apply_runtime_proxy_to_builder(builder, \"tool.weather\");\n        let client = builder.build()?;\n\n        let response = client.get(&url).send().await?;\n        let status = response.status();\n\n        if !status.is_success() {\n            anyhow::bail!(\n                \"wttr.in returned HTTP {status} for location '{location}'. \\\n                 Check that the location is valid.\"\n            );\n        }\n\n        let body = response.text().await?;\n\n        // wttr.in returns a plain-text error string (not JSON) for unknown locations.\n        if !body.trim_start().starts_with('{') {\n            anyhow::bail!(\n                \"wttr.in could not resolve location '{location}'. \\\n                 Try a city name, airport code, GPS coordinates (lat,lon), or zip code.\"\n            );\n        }\n\n        let parsed: WttrResponse = serde_json::from_str(&body).map_err(|e| {\n            ::zeroclaw_log::record!(\n                WARN,","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/weather_tool.rs#L143-L179","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the location string resolves (try it in a browser at wttr.in/<location>) and correct spelling/format","Retry with exponential backoff and jitter — 5xx and rate-limit responses are transient","Reduce polling frequency or cache responses; wttr.in data changes at most hourly","If the outage persists, wait or switch location format (city, IATA code like JFK, 'lat,lon', or zip)"],"exampleFix":"// before\n{\"location\":\"San Francisko\"}  // wttr.in returned HTTP 404\n// after\n{\"location\":\"San Francisco\"}","handlingStrategy":"retry","validationCode":"// Pre-check the location resolves cheaply before polling\n// (format guidance: city, IATA code, \"lat,lon\", zip)\nfn plausible_location(loc: &str) -> bool {\n    !loc.trim().is_empty() && loc.len() < 64\n}","typeGuard":null,"tryCatchPattern":"Err(e) if e.to_string().starts_with(\"wttr.in returned HTTP\") => {\n    if e.to_string().contains(\"404\") { /* fix location, no retry */ }\n    else { backoff_and_retry().await /* 5xx/429 are transient */ }\n}","preventionTips":["Cache weather responses for at least an hour","Add jittered backoff around any free public API","Normalize locations to canonical forms (city/IATA/lat,lon) before calling"],"tags":["weather","http","external-api","rate-limit","wttr"],"backgroundTag":"http-error-response","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}