{"record":{"id":"24a84f5e74fd861e","repo":"jackwener/OpenCLI","slug":"lichess-user-lichess-user-username-returned","errorCode":null,"errorMessage":"lichess user: Lichess user \"${username}\" returned empty payload.","messagePattern":"lichess user: Lichess user \"(.+?)\" returned empty payload\\.","errorType":"error_code","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/lichess/user.js","lineNumber":46,"sourceCode":"        'seenAt',\n        'gamesAll',\n        'gamesWin',\n        'gamesLoss',\n        'gamesDraw',\n        'topPerfName',\n        'topPerfRating',\n        'topPerfGames',\n        'fideRating',\n        'country',\n        'bio',\n        'url',\n    ],\n    func: async (args) => {\n        const username = requireUsername(args.username);\n        const url = `${LICHESS_BASE}/api/user/${encodeURIComponent(username)}`;\n        const body = await lichessFetch(url, 'lichess user');\n        if (!body || typeof body !== 'object') {\n            throw new EmptyResultError('lichess user', `Lichess user \"${username}\" returned empty payload.`);\n        }\n        // Lichess marks closed accounts with `disabled: true` and strips data.\n        // Surface as EmptyResultError instead of a row of nulls (silent-fallback).\n        if (body.disabled === true) {\n            throw new EmptyResultError('lichess user', `Lichess user \"${username}\" is closed/disabled.`);\n        }\n        const perfs = body.perfs && typeof body.perfs === 'object' ? body.perfs : {};\n        // Pick the perf with the most games (excluding puzzle/storm/racer ephemera).\n        const playablePerfs = Object.entries(perfs).filter(([k, v]) => v && typeof v === 'object' && !['puzzle', 'storm', 'racer', 'streak'].includes(k));\n        let topPerfName = null;\n        let topPerfRating = null;\n        let topPerfGames = null;\n        for (const [name, p] of playablePerfs) {\n            const games = typeof p.games === 'number' ? p.games : 0;\n            if (topPerfGames == null || games > topPerfGames) {\n                topPerfName = name;\n                topPerfGames = games;\n                topPerfRating = typeof p.rating === 'number' ? p.rating : null;","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/lichess/user.js#L28-L64","documentation":"lichess user fetches a user profile and expects a JSON object body. If the payload is falsy or not an object, it throws EmptyResultError stating the user returned an empty payload. The command intentionally avoids rendering a row of nulls (silent fallback) and surfaces the problem instead.","triggerScenarios":"Calling lichess user with a username that Lichess resolves to an empty/non-object body (proxy or cache stripping the body), a transient API response with no JSON, or validation passing but the endpoint returning null.","commonSituations":"Intermittent Lichess API/CDN issues; usernames with unusual casing resolved oddly; network middleware (proxy) truncating responses; user in the middle of username change.","solutions":["Retry the request — empty payloads are often transient","Verify the username exists at lichess.org/@/<username> in a browser","Check username spelling/casing (Lichess is case-insensitive but the account must exist)","If the account is closed, expect the distinct 'closed/disabled' error instead"],"exampleFix":"// before\nconst body = await lichessFetch(url, 'lichess user');\n// after\nlet body = await lichessFetch(url, 'lichess user');\nif (!body || typeof body !== 'object') body = await lichessFetch(url, 'lichess user'); // retry once","handlingStrategy":"retry","validationCode":"// pre-flight reachability\nconst head = await fetch('https://lichess.org/api/user/ornicar');\nif (!head.ok) console.warn('Lichess API unhealthy — expect empty payloads');","typeGuard":"const isUserProfile = (b) => b !== null && typeof b === 'object' && typeof b.username === 'string';","tryCatchPattern":"try {\n  await lichessUser(username);\n} catch (e) {\n  if (e.name === 'EmptyResultError' && String(e.message).includes('empty payload')) {\n    await sleep(1000); /* retry once */\n  } else throw e;\n}","preventionTips":["Retry transient empty responses before surfacing errors","Validate usernames on lichess.org first","Avoid middlewares/proxies that can truncate bodies","Distinguish closed accounts (disabled:true) from empty payloads"],"tags":["empty-result","lichess","api","payload"],"backgroundTag":"empty-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}