jackwener/OpenCLI · warning · EmptyResultError
Chess.com returned 404 for ${url}
Error message
Chess.com returned 404 for ${url} What it means
An EmptyResultError thrown when the Chess.com API responds with HTTP 404 for the requested URL. The library deliberately maps 404 to the empty-result family: the endpoint exists but no resource was found for that player/game/month, which callers usually want to treat as 'no data' rather than a hard failure.
Source
Thrown at clis/chess/utils.js:54
`Invalid Chess.com game URL: "${value}"`,
'Expected https://www.chess.com/game/live/<id> or https://www.chess.com/game/daily/<id>.',
);
}
return { kind: m[1].toLowerCase(), id: m[2] };
}
export async function chessApi(path, fetchImpl = fetch) {
const url = path.startsWith('http') ? path : `${API_BASE}${path}`;
let resp;
try {
resp = await fetchImpl(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });
} catch (error) {
throw new CommandExecutionError(`Failed to fetch Chess.com API ${url}: ${error?.message || error}`);
}
if (!resp || typeof resp !== 'object') {
throw new CommandExecutionError(`Chess.com API returned an invalid response object for ${url}`);
}
if (resp.status === 404) throw new EmptyResultError(`Chess.com returned 404 for ${url}`);
if (!resp.ok) throw new CommandExecutionError(`Chess.com API returned HTTP ${resp.status} for ${url}`);
let payload;
try {
payload = await resp.json();
} catch (error) {
throw new CommandExecutionError(`Chess.com API returned malformed JSON for ${url}: ${error?.message || error}`);
}
if (!isPlainObject(payload)) {
throw new CommandExecutionError(`Chess.com API returned an unexpected payload shape for ${url}`);
}
return payload;
}
/** Pull rating + record fields out of a stats sub-object (`chess_rapid` etc). */
export function summarizeStats(stats, kind) {
const k = stats?.[kind];
if (!k) return null;
if (!isPlainObject(k)) {View on GitHub (pinned to 49907e53dc)
Solutions
- Double-check the username spelling (note validateUsername lowercases it first).
- Confirm the player/game exists on chess.com in a browser.
- Catch EmptyResultError in the caller and render a 'not found' message instead of failing.
- For archives, derive valid YYYY/MM ranges from the player's joined date.
Example fix
// before
const rows = await chessStats({ username: 'hikarru' }); // typo -> 404
// after
try {
const rows = await chessStats({ username: 'hikaru' });
} catch (e) {
if (e.name === 'EmptyResultError') return console.log('Player not found');
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check existence with the profile endpoint:
const profile = await chessApi(`/player/${encodeURIComponent(username)}`); // 404 here means user does not exist Type guard
function isEmptyResult(e) {
return e instanceof Error && e.name === 'EmptyResultError' && /returned 404/.test(e.message);
} Try / catch
try {
const rows = await chessStats({ username });
} catch (e) {
if (e.name === 'EmptyResultError') {
return console.log(`No Chess.com data found for ${username}.`);
}
throw e;
} Prevention
- Verify usernames/ids on chess.com before batch queries.
- Treat EmptyResultError as 'not found', not a crash.
- Clamp archive months to the player's join date onward.
When it happens
Trigger: Querying /player/<username>/stats or monthly archives for a username that does not exist, a game id that does not exist, or a YYYY/MM archive month with no games for an existing player.
Common situations: Typo in the username; querying a player who closed/renamed their account; requesting a month before the account existed; stale game id from an old link.
Related errors
- crates.io returned 404 for ${url}.
- Maven Central returned 404 for ${url}.
- zhihu answer-detail
- bilibili creator-stats ${bvid}
- Chess.com has no game archives for ${username}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8ee5ff58f2ca8ece.
Report an issue: GitHub.