jackwener/OpenCLI · error · CommandExecutionError

Chess.com game archive entry has malformed player objects

Error message

Chess.com game archive entry has malformed player objects

What it means

After validating the game URL, mapGameRow() requires both game.white and game.black to be plain objects so it can read usernames, ratings, and results for each side. This throw fires when either player field is missing (and thus coerced via || {}) in a way that fails the object check — i.e. it is a non-object truthy value such as a string, number, or array.

Source

Thrown at clis/chess/utils.js:129

    const cleaned = (namePart ? namePart[1] : tail).replace(/-/g, ' ').trim();
    return cleaned;
}

/**
 * Map a Chess.com game record (from the monthly archive) to a flat row.
 * The viewer perspective controls win/loss orientation.
 */
export function mapGameRow(game, viewerUsername) {
    if (!isPlainObject(game)) {
        throw new CommandExecutionError('Chess.com game archive entry is not an object');
    }
    if (typeof game.url !== 'string' || !/^https:\/\/www\.chess\.com\/game\/(?:live|daily)\/\d+(?:$|[/?#])/i.test(game.url)) {
        throw new CommandExecutionError('Chess.com game archive entry is missing a stable game URL');
    }
    const white = game?.white || {};
    const black = game?.black || {};
    if (!isPlainObject(white) || !isPlainObject(black)) {
        throw new CommandExecutionError('Chess.com game archive entry has malformed player objects');
    }
    if (typeof white.username !== 'string' || !white.username.trim() || typeof black.username !== 'string' || !black.username.trim()) {
        throw new CommandExecutionError('Chess.com game archive entry is missing stable player identities');
    }
    const viewerLower = String(viewerUsername || '').toLowerCase();
    const viewerIsWhite = String(white.username || '').toLowerCase() === viewerLower;
    const viewerIsBlack = String(black.username || '').toLowerCase() === viewerLower;
    if (!viewerIsWhite && !viewerIsBlack) {
        throw new CommandExecutionError('Chess.com game archive entry does not include the requested player');
    }
    const me = viewerIsWhite ? white : black;
    const opp = viewerIsWhite ? black : white;
    const eco = game?.eco || '';
    return {
        date: formatDate(game?.end_time),
        time_class: game?.time_class || '',
        rated: game?.rated === true,
        my_color: viewerIsWhite ? 'white' : 'black',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-fetch the monthly archive — pub archive entries always carry white/black as objects
  2. Fix the intermediate transform that replaced player objects with scalars
  3. In fixtures use white: { username: 'a', rating: 1500, result: 'win' } shape
  4. Add a filter that drops entries failing the player-object shape before mapping

Example fix

// before
const game = { url, white: 'hikaru', black: { username: 'magnus' } };
// after
const game = { url, white: { username: 'hikaru', rating: 2800, result: 'win' }, black: { username: 'magnus', rating: 2850, result: 'loss' } };
Defensive patterns

Strategy: validation

Validate before calling

if (!isPlain(game?.white) || !isPlain(game?.black)) {
  throw new Error('game.white and game.black must be player objects');
}
function isPlain(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }

Type guard

function hasPlayerObjects(g) {
  const plain = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
  return plain(g?.white) && plain(g?.black);
}

Try / catch

try {
  row = mapGameRow(game, user);
} catch (err) {
  if (String(err.message).includes('malformed player objects')) {
    console.warn('Skipping entry: white/black are not player objects');
  } else { throw err; }
}

Prevention

When it happens

Trigger: Archive entry where game.white or game.black is a truthy non-object (e.g. white: "hikaru" or white: [1500]) instead of { username, rating, result }, encountered while mapping rows for a player.

Common situations: A pre-processing step collapsed player objects into usernames or ratings; hand-written fixtures using shorthand; Chess.com schema drift on archive entries; passing entries from a different endpoint (e.g. a game summary endpoint with different player representation).

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/f73fd4f4b3e1a714. Report an issue: GitHub.