jackwener/OpenCLI · error · CommandExecutionError
Chess.com callback returned an invalid response object for $
Error message
Chess.com callback returned an invalid response object for ${url} What it means
This library fetches a single Chess.com game via the internal callback endpoint /callback/{kind}/game/{id}. After the fetch resolves, it expects a valid Response-like object; if fetch resolved with null, undefined, or a non-object, the command throws CommandExecutionError. This is a defensive invariant check against a misbehaving fetch implementation or a mocked/patched global fetch.
Source
Thrown at clis/chess/game.js:96
{ name: 'game-url', type: 'string', required: true, positional: true, help: 'Full game URL, e.g. https://www.chess.com/game/live/168842570216' },
],
columns: [
'kind', 'game_id', 'date',
'white', 'white_rating', 'black', 'black_rating',
'result', 'winner_color', 'termination',
'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
- Check that any global fetch mock/polyfill returns a Response-like object (at minimum {status, ok, json()}) for every matched URL
- Fix unmatched-route behavior in HTTP mocking libraries (e.g. nock/msw) so unmatched requests return a Response instead of undefined
- Run in a runtime with spec-compliant fetch (Node 18+ or undici) instead of a custom polyfill
Example fix
// before (broken mock)
global.fetch = async () => undefined;
// after
const resp = new Response(JSON.stringify({ game: { pgnHeaders: { White: 'a', Black: 'b', Result: '1-0' } } }), { status: 200, headers: { 'content-type': 'application/json' } });
global.fetch = async () => resp; Defensive patterns
Strategy: type-guard
Validate before calling
// before calling the command, ensure your fetch environment is spec-compliant
if (typeof globalThis.fetch !== 'function') throw new Error('fetch unavailable'); Type guard
function isResponseLike(r) { return !!r && typeof r === 'object' && typeof r.status === 'number' && typeof r.ok === 'boolean' && typeof r.json === 'function'; } Try / catch
try {
const rows = await chessGameCmd(url);
} catch (e) {
if (/invalid response object/.test(e.message)) {
// fix or replace the fetch polyfill/mock, then retry
} else throw e;
} Prevention
- Never stub fetch with functions returning undefined/null; always return a Response object
- Test against real fetch (Node 18+) in CI
- Pin mocking libs (nock/msw) and configure a fallback for unmatched routes
When it happens
Trigger: fetch() at clis/chess/game.js:91 resolves to a falsy value or a non-object (e.g. a test stub returning undefined, a proxy/patched fetch returning null, or a non-standard runtime whose fetch resolves non-Response values).
Common situations: Running under a test harness with an incomplete fetch mock; custom Node environments with a polyfilled fetch that violates the spec; code interception (e.g. an HTTP mocking lib misconfigured to return undefined for unmatched routes).
Related errors
- FETCH_ERROR
- archive search request failed: ${error?.message || error}
- archive wayback request failed: ${error?.message || error}
- ${label} request failed: ${err?.message ?? err}
- 字幕获取失败: ${err?.message || err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/06593a4d75670e28.
Report an issue: GitHub.