jackwener/OpenCLI · warning · EmptyResultError

lichess user: Lichess user "${username}" is closed/disabled.

Error message

lichess user: Lichess user "${username}" is closed/disabled.

What it means

This EmptyResultError is thrown when the Lichess API reports the requested account as closed or disabled (`disabled: true`). The library deliberately converts this into an EmptyResultError rather than rendering a row of nulls, which would look like a silent fallback. It means the user exists (or existed) but the account is no longer active.

Source

Thrown at clis/lichess/user.js:51

        'topPerfName',
        'topPerfRating',
        'topPerfGames',
        'fideRating',
        'country',
        'bio',
        'url',
    ],
    func: async (args) => {
        const username = requireUsername(args.username);
        const url = `${LICHESS_BASE}/api/user/${encodeURIComponent(username)}`;
        const body = await lichessFetch(url, 'lichess user');
        if (!body || typeof body !== 'object') {
            throw new EmptyResultError('lichess user', `Lichess user "${username}" returned empty payload.`);
        }
        // Lichess marks closed accounts with `disabled: true` and strips data.
        // Surface as EmptyResultError instead of a row of nulls (silent-fallback).
        if (body.disabled === true) {
            throw new EmptyResultError('lichess user', `Lichess user "${username}" is closed/disabled.`);
        }
        const perfs = body.perfs && typeof body.perfs === 'object' ? body.perfs : {};
        // Pick the perf with the most games (excluding puzzle/storm/racer ephemera).
        const playablePerfs = Object.entries(perfs).filter(([k, v]) => v && typeof v === 'object' && !['puzzle', 'storm', 'racer', 'streak'].includes(k));
        let topPerfName = null;
        let topPerfRating = null;
        let topPerfGames = null;
        for (const [name, p] of playablePerfs) {
            const games = typeof p.games === 'number' ? p.games : 0;
            if (topPerfGames == null || games > topPerfGames) {
                topPerfName = name;
                topPerfGames = games;
                topPerfRating = typeof p.rating === 'number' ? p.rating : null;
            }
        }
        const counts = body.count && typeof body.count === 'object' ? body.count : {};
        const profile = body.profile && typeof body.profile === 'object' ? body.profile : {};
        return [{

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the account status on lichess.org — if it is closed, the data is intentionally unavailable
  2. Handle EmptyResultError in your caller and treat it as 'account deactivated', not as a network failure
  3. If this is unexpected, double-check the username spelling for a close-but-active account
  4. Use a different data source (e.g. archived data) if historical info about the closed account is needed

Example fix

// before
const user = await user(username); // throws on disabled accounts
// after
let user;
try { user = await user(username); }
catch (e) {
  if (e instanceof EmptyResultError) { console.warn('account closed/disabled'); user = null; }
  else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Cannot pre-validate account status without the API call itself.
// Best pre-check: confirm the handle exists and is active via a HEAD/GET before processing.
const res = await fetch(`https://lichess.org/api/user/${encodeURIComponent(name)}`);
const body = await res.json();
if (body?.disabled === true) return null; // account closed

Type guard

function isActiveAccount(body) {
  return typeof body === 'object' && body !== null && body.disabled !== true;
}

Try / catch

try {
  const profile = await user(name);
} catch (e) {
  if (e instanceof EmptyResultError) {
    console.warn(`Account "${name}" is closed/disabled; skipping.`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the `lichess user` command (via `user()`) for a username whose Lichess API response body contains `disabled: true`. This happens after the payload passes the non-empty object check, so the API did respond but with a deactivated account.

Common situations: Looking up a player who closed or was banned on Lichess; querying stale usernames from an old dataset or ratings list; typos that coincidentally match a disabled account handle.

Related errors


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