jackwener/OpenCLI · error · CommandExecutionError
Chess.com game archive entry is not an object
Error message
Chess.com game archive entry is not an object
What it means
mapGameRow() maps one entry from a Chess.com monthly games archive into a flat row. The first guard requires each game entry to be a plain object; if an entry in the games array is null, an array, or a scalar, this error is thrown. It protects the rest of the mapper from dereferencing malformed entries.
Source
Thrown at clis/chess/utils.js:121
* (`https://www.chess.com/openings/Reti-Opening-Nimzo-Larsen-Variation-2...g6-...`).
* Returns '' for short-code eco values (`A01`) where no name is encoded.
*/
export function openingName(eco) {
if (typeof eco !== 'string' || !eco.startsWith('http')) return '';
const tail = eco.replace(/\/+$/, '').split('/').pop() || '';
if (!tail) return '';
const namePart = tail.match(/^([^.]+?)(?:-\d|\.\.\.|$)/);
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');
}View on GitHub (pinned to 49907e53dc)
Solutions
- Ensure each element passed to mapGameRow is a single game object — map over data.games and filter with isPlainObject first
- Parse JSON entries before mapping if your data source returns strings
- Filter null/malformed entries from the archive array before mapping
- Re-fetch the archive if Chess.com returned an unexpected structure
Example fix
// before const rows = archive.games.map((g) => mapGameRow(g, user)); // after const rows = archive.games.filter(isPlainObject).map((g) => mapGameRow(g, user));
Defensive patterns
Strategy: type-guard
Validate before calling
const games = archive?.games ?? [];
for (const g of games) {
if (g === null || typeof g !== 'object' || Array.isArray(g)) {
throw new Error('archive contains a non-object game entry');
}
} Type guard
function isGameEntry(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v) &&
typeof v.url === 'string' && v.url.startsWith('https://www.chess.com/game/');
} Try / catch
try {
rows = games.map((g) => mapGameRow(g, user));
} catch (err) {
if (String(err.message).includes('archive entry is not an object')) {
rows = games.filter(isGameEntry).map((g) => mapGameRow(g, user));
} else { throw err; }
} Prevention
- Always pass a single game object, never the archive wrapper or array
- Parse JSON-string entries before mapping
- Filter null/malformed entries out of archive.games first
- Use isPlainObject as a standard pre-map filter in pipelines
When it happens
Trigger: An element of the games array returned by /pub/player/{user}/games/{yyyy}/{mm} (iterated by row()) is not a plain object — e.g. null entries, or the caller passed the whole archive object/array instead of a single game entry.
Common situations: Caller accidentally passes the entire {games:[...]} wrapper or the archive array instead of one element; Chess.com includes null entries in an archive; a custom fetch/mock returns entries as JSON strings that were never parsed.
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
- Chess.com game archive entry has malformed player objects
- Chess.com game archive entry is missing stable player identi
- Chess.com stats payload for ${kind} is not an object
- Chess.com stats payload for ${kind}.last is not an object
- Chess.com stats payload for ${kind}.best is not an object
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c7e712cb5b929ed0.
Report an issue: GitHub.