{"record":{"id":"2a8164893c985156","repo":"jackwener/OpenCLI","slug":"game-url-is-required","errorCode":null,"errorMessage":"<game-url> is required","messagePattern":"<game-url> is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/chess/utils.js","lineNumber":32,"sourceCode":"    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}\n\nexport async function chessApi(path, fetchImpl = fetch) {\n    const url = path.startsWith('http') ? path : `${API_BASE}${path}`;\n    let resp;\n    try {\n        resp = await fetchImpl(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });\n    } catch (error) {\n        throw new CommandExecutionError(`Failed to fetch Chess.com API ${url}: ${error?.message || error}`);\n    }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/chess/utils.js#L14-L50","documentation":"An ArgumentError thrown by parseGameUrl when the game-url argument is missing or trims to an empty string. A game URL is required to extract the game kind (live/daily) and numeric game id before any Chess.com game endpoint can be queried.","triggerScenarios":"Invoking a game command without the --game-url argument, or passing an empty/whitespace-only value.","commonSituations":"Forgetting the flag entirely; a shell variable holding the URL is unset so the flag expands to an empty string (--game-url \"$GAME_URL\" with GAME_URL='').","solutions":["Provide the game URL, e.g. https://www.chess.com/game/live/123456789.","Verify the shell variable or config value feeding the flag is set and non-empty.","Add a required-argument check at the CLI layer for clearer usage output."],"exampleFix":"// before\nawait chessGame({ gameUrl: process.env.LAST_GAME }); // unset -> throws\n// after\nif (!process.env.LAST_GAME) throw new Error('LAST_GAME is required');\nawait chessGame({ gameUrl: process.env.LAST_GAME });","handlingStrategy":"validation","validationCode":"function requireGameUrl(value) {\n  const s = String(value ?? '').trim();\n  if (!s) throw new Error('game URL is required before calling the chess API');\n  return s;\n}","typeGuard":"function hasGameUrl(args) {\n  return typeof args.gameUrl === 'string' && args.gameUrl.trim().length > 0;\n}","tryCatchPattern":"try {\n  const game = await chessGame({ gameUrl });\n} catch (e) {\n  if (e.name === 'ArgumentError' && /game-url is required/i.test(e.message)) {\n    console.error('Usage: opencli chess game --game-url https://www.chess.com/game/live/<id>');\n  } else throw e;\n}","preventionTips":["Make --game-url a required flag with usage help.","Guard unset shell variables before expanding them into flags.","Trim input early to catch whitespace-only values."],"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"}