jackwener/OpenCLI · critical · CommandExecutionError
${label} request failed: ${err.message}
Error message
${label} request failed: ${err.message} What it means
This CommandExecutionError wraps a low-level fetch failure when the HTTP request to wttr.in never completes — the fetch call itself rejected (DNS failure, connection refused/reset, timeout, TLS error). The label ('wttr forecast', etc.) is prefixed and the underlying err.message is appended for diagnosis.
Source
Thrown at clis/wttr/utils.js:25
export const WTTR_BASE = 'https://wttr.in';
const UA = 'opencli-wttr/1.0';
export function requireString(value, name) {
if (typeof value !== 'string' || !value.trim()) {
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;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Verify network connectivity and DNS for wttr.in (curl -v 'https://wttr.in/Paris?format=j1')
- Configure proxy environment variables (HTTPS_PROXY) if behind a proxy
- Retry with backoff for transient connection issues
- Set up a fallback weather source (e.g. NWS for US locations)
Example fix
// before
const body = await wttrFetch(location, 'wttr forecast'); // throws offline
// after
try {
const body = await wttrFetch(location, 'wttr forecast');
} catch (err) {
if (err instanceof CommandExecutionError) body = await fallbackFetch(location);
else throw err;
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight connectivity check
try {
await fetch('https://wttr.in/?format=j1', { method: 'HEAD' });
} catch {
throw new Error('wttr.in is unreachable; check network/proxy');
} Try / catch
try {
result = await forecast({ location });
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('request failed')) {
// transient network issue: retry with backoff
result = await withRetry(() => forecast({ location }), 3);
} else throw err;
} Prevention
- Set HTTPS_PROXY/HTTP_PROXY when behind corporate proxies
- Implement retry with exponential backoff for transient failures
- Monitor wttr.in uptime and cache last successful responses as fallback
When it happens
Trigger: wttrFetch calls fetch(`https://wttr.in/${encodeURIComponent(location)}?format=j1`) and the promise rejects before a response object exists.
Common situations: Being offline or behind a blocking corporate proxy; DNS resolution failure; firewall blocking wttr.in; Node without network access in CI; TLS interception.
Related errors
- FETCH_ERROR
- archive search request failed: ${error?.message || error}
- archive wayback request failed: ${error?.message || error}
- ${label} request failed: ${err?.message ?? err}
- Bilibili creator comparison request failed: ${detail}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e1d8d02fc9223d83.
Report an issue: GitHub.