jackwener/OpenCLI · error · CommandExecutionError
Chess.com callback returned HTTP ${resp.status} for ${url}
Error message
Chess.com callback returned HTTP ${resp.status} for ${url} What it means
After handling 404, any other non-OK response (resp.ok false) from the Chess.com callback endpoint throws CommandExecutionError with the HTTP status. This surfaces upstream API problems — rate limiting, 5xx outages, redirects to challenge pages — as an explicit command error instead of a confusing JSON parse failure.
Source
Thrown at clis/chess/game.js:102
'eco', 'time_control', 'rated', 'ply_count', 'url',
],
func: async (kwargs) => {
const { kind, id } = parseGameUrl(kwargs['game-url']);
const url = `${CALLBACK_BASE}/${kind}/game/${id}`;
let resp;
try {
resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });
} catch (error) {
throw new CommandExecutionError(`Failed to fetch Chess.com callback ${url}: ${error?.message || error}`);
}
if (!resp || typeof resp !== 'object') {
throw new CommandExecutionError(`Chess.com callback returned an invalid response object for ${url}`);
}
if (resp.status === 404) {
throw new EmptyResultError(`Chess.com has no ${kind} game with id ${id}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`Chess.com callback returned HTTP ${resp.status} for ${url}`);
}
let payload;
try {
payload = await resp.json();
} catch (error) {
throw new CommandExecutionError(`Chess.com callback returned malformed JSON for ${url}: ${error?.message || error}`);
}
return [summarizeGame({ kind, id, payload })];
},
});
export const __test__ = { parseGameUrl, summarizeGame };
View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the status in the message and retry after a backoff for 429/5xx
- Send a realistic User-Agent and avoid high request rates — the library already sets UA, so add spacing between calls
- For persistent 403, run from a different network/IP or use the public pubsub API endpoints instead of the callback endpoint
Example fix
// before: naive loop
for (const id of ids) await getGame(id);
// after: throttle + backoff
for (const id of ids) {
try { await getGame(id); }
catch (e) { if (/HTTP 429|HTTP 5/.test(e.message)) await sleep(5000); }
await sleep(1000);
} Defensive patterns
Strategy: retry
Validate before calling
// no pre-call validation possible; monitor status before retrying // e.g. check https://status.chess.com or reduce request frequency
Try / catch
async function withRetry(fn, attempts = 3) {
for (let i = 0; ; i++) {
try { return await fn(); }
catch (e) {
const m = /HTTP (\d{3})/.exec(e.message || '');
const status = m ? Number(m[1]) : 0;
if (i < attempts - 1 && (status === 429 || status >= 500)) { await new Promise(r => setTimeout(r, 2 ** i * 1000)); continue; }
throw e;
}
}
} Prevention
- Throttle requests (>=1s between calls) to avoid 429
- Keep a realistic User-Agent on every request
- Avoid datacenter IPs that trigger 403 bot challenges
- Back off exponentially on 5xx instead of tight-looping
When it happens
Trigger: The fetch to https://www.chess.com/callback/{kind}/game/{id} returns any status other than 2xx/404: 403 (bot challenge/Cloudflare), 429 (rate limited), 5xx (Chess.com outage).
Common situations: Hammering the API in a loop without delays (429); Chess.com serving a bot-detection page to datacenter IPs (403); temporary Chess.com incidents (500/502/503).
Related errors
- autohome ${contextHint} HTTP ${resp.status}
- Ctrip flight API returned HTTP ${status || 'unknown'}
- dongchedi ${contextHint} HTTP ${resp.status}
- eastmoney convertible failed: HTTP ${resp.status}
- HTTP_ERROR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/df81f43b58fc9ba8.
Report an issue: GitHub.