jackwener/OpenCLI · error · CommandExecutionError

Chess.com monthly archive payload is missing games array

Error message

Chess.com monthly archive payload is missing games array

What it means

Each monthly archive fetched via chessApi(archives[i]) must contain a games array. If the payload for a month lacks .games, the command throws CommandExecutionError, indicating the monthly endpoint response no longer matches the expected schema.

Source

Thrown at clis/chess/games.js:52

    func: async (kwargs) => {
        const username = validateUsername(kwargs.username);
        const limit = parseLimit(kwargs.limit);
        const archivesList = await chessApi(`/player/${encodeURIComponent(username)}/games/archives`);
        if (!Array.isArray(archivesList.archives)) {
            throw new CommandExecutionError('Chess.com archives payload is missing archives array');
        }
        const archives = archivesList.archives.slice().reverse();
        if (archives.length === 0) {
            throw new EmptyResultError(`Chess.com has no game archives for ${username}`);
        }
        const rows = [];
        for (let i = 0; i < archives.length && i < MAX_ARCHIVE_FETCHES && rows.length < limit; i++) {
            if (typeof archives[i] !== 'string' || !archives[i].startsWith('https://api.chess.com/pub/player/')) {
                throw new CommandExecutionError('Chess.com archives payload contains an unexpected archive URL');
            }
            const monthly = await chessApi(archives[i]);
            if (!Array.isArray(monthly.games)) {
                throw new CommandExecutionError('Chess.com monthly archive payload is missing games array');
            }
            const games = monthly.games.slice().reverse();
            for (const g of games) {
                rows.push(mapGameRow(g, username));
                if (rows.length >= limit) break;
            }
        }
        if (rows.length === 0) {
            throw new EmptyResultError(`Chess.com has games archives for ${username} but no games in the most recent ${MAX_ARCHIVE_FETCHES} months`);
        }
        return rows.slice(0, limit);
    },
});

export const __test__ = { parseLimit };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. curl the specific monthly archive URL and inspect the JSON structure
  2. Pin to a known-good version of this library or patch the expected field if Chess.com renamed the key
  3. Bypass proxies/VPN that may alter responses

Example fix

// before
const monthly = await chessApi(url);
// after
const monthly = await chessApi(url);
if (monthly && monthly.chess_games) { monthly.games = monthly.chess_games; } // adapt renamed field
if (!Array.isArray(monthly.games)) throw new CommandExecutionError('missing games array');
Defensive patterns

Strategy: type-guard

Type guard

function hasGames(p) { return p != null && typeof p === 'object' && Array.isArray(p.games); }

Try / catch

try {
  await gamesCmd(username);
} catch (e) {
  if (/missing games array/.test(e.message)) {
    // inspect the monthly payload; check Chess.com API for schema changes
  } else throw e;
}

Prevention

When it happens

Trigger: The GET of a monthly archive URL (https://api.chess.com/pub/player/{u}/games/{yyyy}/{mm}) succeeds but the body has no games array — Chess.com schema change, an error body returned with 200, or an intermediate/proxy response.

Common situations: Chess.com API format changes; mocked API servers missing the games key; edge/CDN error pages returned with 200 status.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/a5dab49b8a5bcc8f. Report an issue: GitHub.