{"record":{"id":"c4f56bc04e6e9b89","repo":"jackwener/OpenCLI","slug":"limit-must-be-a-positive-integer-c4f56b","errorCode":null,"errorMessage":"limit must be a positive integer","messagePattern":"limit must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/twitter/followers.js","lineNumber":96,"sourceCode":"    browser: true,\n    args: [\n        {\n            name: 'user',\n            positional: true,\n            type: 'string',\n            required: false,\n            help: 'Twitter/X handle (with or without @). Omit to fetch followers of the currently logged-in account.',\n        },\n        { name: 'limit', type: 'int', default: 50, help: 'Maximum number of follower rows to return (default 50). Must be a positive integer.' },\n    ],\n    // Preserve the historical three-column contract even though the GraphQL\n    // payload also contains per-user relationship counts. Use `twitter profile`\n    // when a dedicated follower count is needed.\n    columns: ['screen_name', 'name', 'bio'],\n    func: async (page, kwargs) => {\n        const limit = kwargs.limit;\n        if (!Number.isInteger(limit) || limit <= 0) {\n            throw new ArgumentError('limit must be a positive integer');\n        }\n\n        const rawUser = String(kwargs.user ?? '').trim();\n        let targetUser = normalizeScreenName(rawUser);\n        if (rawUser && !targetUser) {\n            throw new ArgumentError('twitter followers user must be a valid Twitter/X handle', 'Example: opencli twitter followers @elonmusk --limit 100');\n        }\n        await page.goto('https://x.com/home');\n        await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n        const cookies = await page.getCookies({ url: 'https://x.com' });\n        const ct0 = cookies.find((cookie) => cookie.name === 'ct0')?.value || null;\n        if (!ct0) {\n            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');\n        }\n\n        if (!targetUser) {\n            // Bridge wraps primitive page.evaluate returns as { session, data:<value> };\n            // unwrap so the href string is usable downstream.","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/followers.js#L78-L114","documentation":"The followers command validates its --limit option before doing any work: it must be an integer greater than 0 (Number.isInteger(limit) && limit > 0). Note the CLI declares type 'int' with default 50, so this error means the value supplied programmatically via kwargs.limit (or a non-integer/fractional CLI value) failed validation. It is an ArgumentError raised immediately, before any browser session or network activity.","triggerScenarios":"Calling the command's func with kwargs.limit set to 0, a negative number, NaN, Infinity, a float like 2.5, or a numeric string like '100' instead of a number.","commonSituations":"Passing a string from a config file or environment variable instead of a parsed int; computing the limit with arithmetic that yields a float; forgetting the default and passing undefined from a wrapper.","solutions":["Pass limit as a positive integer, e.g. --limit 100","Coerce and validate before calling: const limit = Math.floor(Number(raw)); if (!Number.isInteger(limit) || limit <= 0) ...","Omit the option to use the default of 50"],"exampleFix":"// before\nopencli twitter followers @elonmusk --limit 0\n// after\nopencli twitter followers @elonmusk --limit 100","handlingStrategy":"validation","validationCode":"function assertLimit(n) {\n  const v = Math.floor(Number(n));\n  if (!Number.isInteger(v) || v <= 0) throw new Error('limit must be a positive integer');\n  return v;\n}\nconst limit = assertLimit(process.env.LIMIT ?? 50);","typeGuard":"const isPositiveInt = (v) => Number.isInteger(v) && v > 0;","tryCatchPattern":"try {\n  await opencli.twitter.followers(user, { limit });\n} catch (err) {\n  if (err.message === 'limit must be a positive integer') {\n    limit = 50; // fall back to default\n  } else throw err;\n}","preventionTips":["Parse --limit with parseInt before passing it","Never pass user-supplied strings directly as limit","Omit the option when the default (50) is acceptable"],"tags":["validation","arguments","cli"],"backgroundTag":"invalid-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}