{"record":{"id":"b4de17a6a464b11f","repo":"jackwener/OpenCLI","slug":"tvmaze-show-id-is-required-and-must-be-a-positive","errorCode":null,"errorMessage":"tvmaze show id is required and must be a positive integer","messagePattern":"tvmaze show id is required and must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/tvmaze/utils.js","lineNumber":20,"sourceCode":"//\n// TVmaze publishes a free, unauthenticated REST API at https://api.tvmaze.com.\n// Docs: https://www.tvmaze.com/api\nimport { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nexport const TVMAZE_BASE = 'https://api.tvmaze.com';\nconst UA = 'opencli-tvmaze-adapter (+https://github.com/jackwener/opencli)';\n\nexport function requireString(value, label) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError(`tvmaze ${label} cannot be empty`);\n    return s;\n}\n\nexport function requireShowId(value) {\n    const raw = value;\n    const n = typeof raw === 'number' ? raw : Number(String(raw ?? '').trim());\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(\n            'tvmaze show id is required and must be a positive integer',\n            'TVmaze show ids appear in the URL: https://www.tvmaze.com/shows/<id>/<slug>.',\n        );\n    }\n    return n;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`tvmaze ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`tvmaze ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tvmaze/utils.js#L2-L38","documentation":"requireShowId validates that the `id` argument is a positive integer before any HTTP request is made, throwing ArgumentError with a hint pointing to how TVmaze show ids appear in URLs. It accepts numbers or numeric strings but rejects anything else — floats, zero, negatives, non-numeric strings, empty values. This fails fast to avoid pointless API calls to /shows/<invalid>.","triggerScenarios":"Calling `tvmaze show` with an id like 'abc', '12.5', '0', '-3', '' , or undefined — e.g. copying the show slug ('game-of-thrones') instead of the numeric id from a TVmaze URL, or passing a name where an id is expected.","commonSituations":"Extracting the wrong URL segment (slug vs id) from a TVmaze link; passing a show name string; spreadsheet/copy errors losing digits; scripts interpolating undefined variables into the id position.","solutions":["Extract the numeric segment from the TVmaze URL: https://www.tvmaze.com/shows/<id>/<slug> — use <id>, not the slug.","If you only know the show name, run `tvmaze search` first and use the returned show.id.","Cast numeric strings carefully; ensure the value is a whole number > 0 before calling.","Catch ArgumentError and display the hint about the URL format to end users."],"exampleFix":"// before\nawait tvmazeShow('game-of-thrones'); // slug, not id\n// after\nawait tvmazeShow(82); // numeric id from tvmaze.com/shows/82/game-of-thrones","handlingStrategy":"validation","validationCode":"function toShowId(v) {\n    const n = typeof v === 'number' ? v : Number(String(v ?? '').trim());\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new Error(`invalid TVmaze show id: ${JSON.stringify(v)}`);\n    }\n    return n;\n}","typeGuard":"function isValidShowId(v) {\n    const n = typeof v === 'number' ? v : Number(String(v ?? '').trim());\n    return Number.isInteger(n) && n > 0;\n}","tryCatchPattern":"try {\n    const show = await tvmazeShow(idArg);\n} catch (err) {\n    if (err instanceof ArgumentError && err.message.includes('positive integer')) {\n        console.error('Pass the numeric id from https://www.tvmaze.com/shows/<id>/<slug>');\n        process.exitCode = 2;\n    } else {\n        throw err;\n    }\n}","preventionTips":["Take the numeric URL segment, never the slug, from TVmaze links","Resolve names to ids with tvmaze search before calling show","Coerce and validate id inputs (Number.isInteger, > 0) at the script boundary","Document that the argument is a TVmaze id, not a name or foreign-provider id"],"tags":["validation","argument-error","input","tvmaze"],"backgroundTag":"invalid-argument-type","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}