jackwener/OpenCLI · critical · CommandExecutionError
Failed to fetch Chess.com API ${url}: ${error?.message || er
Error message
Failed to fetch Chess.com API ${url}: ${error?.message || error} What it means
A CommandExecutionError thrown when the fetch itself rejects — the HTTP request to the Chess.com API never completed. The original error message is embedded, and the failing URL is included for diagnosis. This happens before any HTTP status can be inspected.
Source
Thrown at clis/chess/utils.js:49
const s = String(value ?? '').trim();
if (!s) throw new ArgumentError('<game-url> is required');
const m = s.match(GAME_URL_RE);
if (!m) {
throw new ArgumentError(
`Invalid Chess.com game URL: "${value}"`,
'Expected https://www.chess.com/game/live/<id> or https://www.chess.com/game/daily/<id>.',
);
}
return { kind: m[1].toLowerCase(), id: m[2] };
}
export async function chessApi(path, fetchImpl = fetch) {
const url = path.startsWith('http') ? path : `${API_BASE}${path}`;
let resp;
try {
resp = await fetchImpl(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });
} catch (error) {
throw new CommandExecutionError(`Failed to fetch Chess.com API ${url}: ${error?.message || error}`);
}
if (!resp || typeof resp !== 'object') {
throw new CommandExecutionError(`Chess.com API returned an invalid response object for ${url}`);
}
if (resp.status === 404) throw new EmptyResultError(`Chess.com returned 404 for ${url}`);
if (!resp.ok) throw new CommandExecutionError(`Chess.com API returned HTTP ${resp.status} for ${url}`);
let payload;
try {
payload = await resp.json();
} catch (error) {
throw new CommandExecutionError(`Chess.com API returned malformed JSON for ${url}: ${error?.message || error}`);
}
if (!isPlainObject(payload)) {
throw new CommandExecutionError(`Chess.com API returned an unexpected payload shape for ${url}`);
}
return payload;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Check network connectivity and confirm https://api.chess.com is reachable (curl the URL).
- On Node <18, polyfill global fetch or upgrade Node so the default fetchImpl exists.
- Configure HTTP(S)_PROXY / agent settings if a corporate proxy is required.
- If you inject a custom fetchImpl, verify it is a working async function returning a Response-like object.
Example fix
// before
const stats = await chessApi('/player/hikaru/stats'); // Node 16: fetch is undefined
// after
import fetch from 'node-fetch';
globalThis.fetch ??= fetch;
const stats = await chessApi('/player/hikaru/stats'); Defensive patterns
Strategy: retry
Validate before calling
// Reachability pre-check before running the workflow:
const ok = await fetch('https://api.chess.com/pub/player/hikaru', { method: 'HEAD' })
.then(() => true)
.catch(() => false);
if (!ok) throw new Error('api.chess.com unreachable; check network/proxy'); Type guard
function isNetworkError(e) {
return e instanceof Error && /Failed to fetch Chess.com API/.test(e.message);
} Try / catch
async function withRetry(fn, { retries = 3, backoffMs = 1000 } = {}) {
for (let i = 0; ; i++) {
try { return await fn(); }
catch (e) {
if (!isNetworkError(e) || i >= retries) throw e;
await new Promise((r) => setTimeout(r, backoffMs * 2 ** i));
}
}
}
const stats = await withRetry(() => chessApi('/player/hikaru/stats')); Prevention
- Verify DNS/proxy reachability of api.chess.com in the deployment environment.
- Ensure Node >= 18 or polyfill global fetch.
- Wrap all chessApi calls in a retry-with-backoff helper.
- If injecting fetchImpl, unit-test that it actually resolves to a Response.
When it happens
Trigger: DNS resolution failure for api.chess.com, connection refused/timeout, TLS errors, offline network, or a custom fetchImpl injected into chessApi that throws (e.g. a stub not configured or a proxy rejecting the request).
Common situations: Corporate proxy or firewall blocking api.chess.com; no internet connection; Node without a global fetch (older Node <18, so fetch is undefined and calling it throws); VPN or DNS misconfiguration.
Related errors
- archive wayback request failed: ${error?.message || error}
- Failed to reach Xiaoyuzhou API: ${getErrorMessage(error)}
- FETCH_ERROR
- coingecko top request failed: ${error?.message || error}
- coingecko trending request failed: ${error?.message || error
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/283ffff85fffa089.
Report an issue: GitHub.