jackwener/OpenCLI · warning · EmptyResultError

Chess.com returned no stats for ${username}

Error message

Chess.com returned no stats for ${username}

What it means

Thrown as an EmptyResultError after the stats command fetches /player/<username>/stats from the Chess.com API and finds no recognizable rating blocks (chess_rapid, chess_blitz, chess_bullet, etc.) to summarize. The call succeeded HTTP-wise, but the payload contained no stats rows for any known time-control kind. It signals an empty result, not a network or auth failure.

Source

Thrown at clis/chess/stats.js:28

cli({
    site: 'chess',
    name: 'stats',
    access: 'read',
    description: 'Chess.com player ratings + win/loss record across game kinds',
    domain: 'api.chess.com',
    strategy: Strategy.PUBLIC,
    browser: false,
    args: [
        { name: 'username', type: 'string', required: true, positional: true, help: 'Chess.com username (case-insensitive)' },
    ],
    columns: ['kind', 'rating_current', 'rating_best', 'wins', 'losses', 'draws'],
    func: async (kwargs) => {
        const username = validateUsername(kwargs.username);
        const stats = await chessApi(`/player/${encodeURIComponent(username)}/stats`);
        const rows = KINDS.map((k) => summarizeStats(stats, k)).filter(Boolean);
        if (rows.length === 0) {
            throw new EmptyResultError(`Chess.com returned no stats for ${username}`);
        }
        return rows;
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the username has played at least one rated game (check the Chess.com profile page for ratings).
  2. Log the raw stats payload to confirm which chess_* keys the API returned and that they match the KINDS list.
  3. If Chess.com changed the payload shape, update KINDS in clis/chess/stats.js to the new key names.
  4. Treat it as an expected empty result in your caller — catch EmptyResultError and show a friendly 'no stats yet' message.

Example fix

// before
const rows = KINDS.map((k) => summarizeStats(stats, k)).filter(Boolean);
if (rows.length === 0) {
  throw new EmptyResultError(`Chess.com returned no stats for ${username}`);
}
// after
const rows = KINDS.map((k) => summarizeStats(stats, k)).filter(Boolean);
if (rows.length === 0) {
  console.warn(`No rated games found for ${username}; showing profile only.`);
  return [];
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Nothing to pre-check locally; optionally verify the player has rated games first:
const profile = await chessApi(`/player/${encodeURIComponent(username)}`);
if (!profile || profile.league === undefined && profile.joined === undefined) {
  console.warn('Player profile looks empty; stats may be empty too.');
}

Type guard

function hasAnyStatsKind(stats, kinds) {
  return kinds.some((k) => stats && typeof stats === 'object' && stats[k] != null);
}

Try / catch

try {
  const rows = await chessStats({ username });
} catch (e) {
  if (e.name === 'EmptyResultError') {
    console.log(`No rated stats for ${username} yet.`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling chessApi('/player/<username>/stats') succeeds but every summarizeStats(stats, k) returns null because none of the KINDS exist in the response — i.e. the resolved user exists but has never played any rated game tracked in the stats endpoint.

Common situations: Querying a brand-new Chess.com account that has only played unrated/casual games; querying a bot or streamer account with stats hidden; a stats payload shape change by Chess.com that renames or removes the chess_* keys.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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