{"record":{"id":"0320a5412fcfc394","repo":"jackwener/OpenCLI","slug":"username-is-required","errorCode":null,"errorMessage":"<username> is required","messagePattern":"<username> is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/chess/utils.js","lineNumber":23,"sourceCode":"import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nexport const API_BASE = 'https://api.chess.com/pub';\nexport const UA = 'Mozilla/5.0 (compatible; opencli/1.0)';\n\nconst USERNAME_RE = /^[a-zA-Z0-9_-]{3,25}$/;\nconst GAME_URL_RE = /^https:\\/\\/www\\.chess\\.com\\/game\\/(live|daily)\\/(\\d+)/i;\n\nexport function isPlainObject(value) {\n    return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isOptionalPlainObject(value) {\n    return value === undefined || value === null || isPlainObject(value);\n}\n\nexport function validateUsername(value) {\n    const s = String(value ?? '').trim().toLowerCase();\n    if (!s) throw new ArgumentError('<username> is required');\n    if (!USERNAME_RE.test(s)) {\n        throw new ArgumentError(`Invalid Chess.com username \"${value}\"`, 'Usernames are 3-25 chars: a-z, 0-9, hyphen, underscore.');\n    }\n    return s;\n}\n\nexport function parseGameUrl(value) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError('<game-url> is required');\n    const m = s.match(GAME_URL_RE);\n    if (!m) {\n        throw new ArgumentError(\n            `Invalid Chess.com game URL: \"${value}\"`,\n            'Expected https://www.chess.com/game/live/<id> or https://www.chess.com/game/daily/<id>.',\n        );\n    }\n    return { kind: m[1].toLowerCase(), id: m[2] };\n}","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/chess/utils.js#L5-L41","documentation":"An ArgumentError thrown by validateUsername when the username argument is missing, empty, or only whitespace. The library normalizes input with String(value ?? '').trim().toLowerCase() and rejects it before any network call, since a username is mandatory for every player-based Chess.com endpoint.","triggerScenarios":"Calling stats/archives/monthly commands with username undefined, null, an empty string, or a value that trims to nothing (e.g. '   ').","commonSituations":"A required CLI flag not passed; reading a username from an unset environment variable or config key that yields undefined; passing null programmatically.","solutions":["Pass a non-empty username string, e.g. opencli chess stats --username hikaru.","Check the env var or config value feeding the argument is set before calling.","Add a CLI-level required-argument check so the user gets usage help instead of this error."],"exampleFix":"// before\nconst stats = await chessStats({ username: process.env.CHESS_USER });\n// after\nif (!process.env.CHESS_USER) throw new Error('CHESS_USER env var is required');\nconst stats = await chessStats({ username: process.env.CHESS_USER });","handlingStrategy":"validation","validationCode":"function requireUsername(value) {\n  const s = String(value ?? '').trim();\n  if (!s) throw new Error('username is required before calling the chess API');\n  return s;\n}","typeGuard":"function hasUsername(args) {\n  return typeof args.username === 'string' && args.username.trim().length > 0;\n}","tryCatchPattern":"try {\n  const rows = await chessStats({ username });\n} catch (e) {\n  if (e.name === 'ArgumentError' && /username is required/i.test(e.message)) {\n    console.error('Usage: opencli chess stats --username <name>');\n  } else throw e;\n}","preventionTips":["Make the username a required CLI flag with usage help.","Check env/config values are set before invoking the library.","Trim and default-coalesce user input early."],"tags":["argument-error","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}