jackwener/OpenCLI · error · CommandExecutionError
${label} returned HTTP ${resp.status}.
Error message
${label} returned HTTP ${resp.status}. What it means
wttrFetch in clis/wttr/utils.js wraps all HTTP calls to wttr.in. After handling fetch network failures and 404s separately, any other non-OK HTTP status (429 rate limit, 5xx server errors, etc.) is raised as a CommandExecutionError with the upstream status code in the message. It signals the wttr.in service itself rejected or failed the request, not that the location was unknown.
Source
Thrown at clis/wttr/utils.js:31
throw new ArgumentError(`--${name} is required`);
}
return value.trim();
}
export async function wttrFetch(location, label) {
// wttr.in path-encodes the location. Spaces → %20 is fine; commas survive.
const url = `${WTTR_BASE}/${encodeURIComponent(location)}?format=j1`;
let resp;
try {
resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });
} catch (err) {
throw new CommandExecutionError(`${label} request failed: ${err.message}`);
}
if (resp.status === 404) {
throw new EmptyResultError(label, `${label} could not find location "${location}".`);
}
if (!resp.ok) {
throw new CommandExecutionError(`${label} returned HTTP ${resp.status}.`);
}
let body;
try {
body = await resp.json();
} catch (err) {
// wttr.in falls back to plain-text "Unknown location" for some bad inputs;
// promote that to EmptyResult instead of pretending we got JSON.
throw new EmptyResultError(label, `${label} returned non-JSON body (likely unknown location).`);
}
return body;
}
// wttr.in's "weatherDesc" / "lang_en" fields are arrays of `{ value: '...' }` objects.
// Single-element 99% of the time but the schema is a list.
export function pickWeatherDesc(arr) {
if (!Array.isArray(arr) || !arr.length) return '';
const first = arr[0];
return typeof first?.value === 'string' ? first.value.trim() : '';View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the request after a short backoff (wttr.in 429/5xx are usually transient).
- If the status is 429, slow down request frequency or cache results instead of re-fetching.
- Check https://wttr.in directly in a browser to confirm the service is up.
- Check local network/proxy configuration that might inject non-200 responses.
- Use an alternative weather source (e.g. the NWS CLI for US locations) if wttr.in stays down.
Example fix
// before
const weather = await body('--location', 'Berlin');
// after
try {
const weather = await body('--location', 'Berlin');
} catch (err) {
if (/returned HTTP (429|5\d\d)/.test(err.message)) {
await new Promise(r => setTimeout(r, 5000));
// retry once
} else throw err;
} Defensive patterns
Strategy: retry
Validate before calling
const resp = await fetch('https://wttr.in/Berlin?format=j1');
if (!resp.ok && resp.status !== 404) {
console.warn(`wttr.in unhealthy (HTTP ${resp.status}), use cached data or another source`);
} Try / catch
try {
const weather = await body('--location', loc);
} catch (err) {
if (/returned HTTP (429|5\d\d)/.test(err.message)) {
await sleep(backoff);
// retry with exponential backoff, fall back to cached data on final failure
} else throw err;
} Prevention
- Cache wttr.in responses (they update hourly at most) instead of refetching per call.
- Add exponential backoff and a cap of 1-2 retries for 429/5xx.
- Monitor wttr.in status before running batch weather jobs.
- Avoid tight loops of requests to wttr.in.
When it happens
Trigger: Calling wttrFetch (via the wttr CLI's body command) when wttr.in responds with a status other than 200 or 404 — e.g. HTTP 429 when rate-limited, 500/502/503 during wttr.in outages or overload.
Common situations: Hammering wttr.in with many rapid requests (it rate-limits aggressively); wttr.in's shared public service being overloaded or down; corporate proxies intercepting the request and returning 403/502; IPv6 connectivity issues causing upstream gateway errors.
Related errors
- Flomo API returned HTTP ${resp.status}
- ${label} failed: HTTP ${response.status}
- Sales Navigator lead search API returned an unexpected respo
- lobsters domain returned HTTP ${resp.status}
- HTTP ${probe.httpStatus} from nowcoder profile API
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9a8a07d1bcedfbaa.
Report an issue: GitHub.