{"record":{"id":"ada9c111b793e781","repo":"jackwener/OpenCLI","slug":"chess-com-callback-returned-no-game-payload","errorCode":null,"errorMessage":"Chess.com callback returned no game payload","messagePattern":"Chess\\.com callback returned no game payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/chess/game.js","lineNumber":22,"sourceCode":" * PGN headers + move data plus per-player metadata.\n */\nimport { cli, Strategy } from '@jackwener/opencli/registry';\nimport { CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\nimport { UA, formatDate, isPlainObject, parseGameUrl } from './utils.js';\n\nconst CALLBACK_BASE = 'https://www.chess.com/callback';\n\nfunction stringOrEmpty(value) {\n    return typeof value === 'string' ? value : '';\n}\n\nfunction scalarOrEmpty(value) {\n    return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' ? value : '';\n}\n\nexport function summarizeGame({ kind, id, payload }) {\n    if (!isPlainObject(payload) || !isPlainObject(payload.game)) {\n        throw new CommandExecutionError('Chess.com callback returned no game payload');\n    }\n    const g = payload.game;\n    if (g.pgnHeaders !== undefined && !isPlainObject(g.pgnHeaders)) {\n        throw new CommandExecutionError('Chess.com callback returned malformed PGN headers');\n    }\n    if (payload.players !== undefined && !isPlainObject(payload.players)) {\n        throw new CommandExecutionError('Chess.com callback returned malformed player metadata');\n    }\n    const players = payload.players || {};\n    const byColor = {};\n    for (const slot of ['top', 'bottom']) {\n        const p = players[slot];\n        if (p !== undefined && !isPlainObject(p)) {\n            throw new CommandExecutionError('Chess.com callback returned malformed player metadata');\n        }\n        if (p?.color) byColor[p.color] = p;\n    }\n    const white = byColor.white || {};","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/chess/game.js#L4-L40","documentation":"summarizeGame validates the raw payload returned by the Chess.com callback before building a row; it throws CommandExecutionError when the payload is not a plain object or lacks a plain-object `game` field, since no summary can be derived without it.","triggerScenarios":"The callback response body is not JSON-shaped as expected (HTML error page parsed weirdly, empty body, API schema change) so payload or payload.game is missing/not an object when summarizeGame runs.","commonSituations":"Chess.com changed their callback response schema; the fetch succeeded but returned an error page; proxies/CDNs returning HTML instead of JSON; version drift between the CLI and the endpoint.","solutions":["Log/inspect the raw callback response to see what was actually returned.","Retry the fetch — a transient bad response can masquerade as a schema problem.","Check whether Chess.com changed the callback response shape and update the CLI's parsing accordingly.","Validate the response is JSON before calling summarizeGame (check content-type and try/catch the parse)."],"exampleFix":"// before\nconst row = summarizeGame({ kind, id, payload }); // payload may be junk\n// after\nif (!isPlainObject(payload) || !isPlainObject(payload.game)) {\n  throw new CommandExecutionError('Chess.com callback returned no game payload');\n}\nconst row = summarizeGame({ kind, id, payload });","handlingStrategy":"type-guard","validationCode":"const body = await resp.text();\nlet payload; try { payload = JSON.parse(body); } catch { throw new Error('Callback response is not JSON'); }","typeGuard":"const isPlainObject = (v) => Object.prototype.toString.call(v) === '[object Object]';\nconst hasGamePayload = (p) => isPlainObject(p) && isPlainObject(p.game);","tryCatchPattern":"try {\n  const row = summarizeGame({ kind, id, payload });\n} catch (err) {\n  if (String(err.message).includes('no game payload')) {\n    console.error('Unexpected callback response; dumping raw body for inspection');\n  } else throw err;\n}","preventionTips":["Validate JSON shape before summarizing","Log raw responses on schema mismatch to detect API changes quickly","Pin CLI version against known endpoint behavior and test with real fixtures"],"tags":["api-response","schema-validation","chess"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}