{"record":{"id":"35e853b8474cda3a","repo":"jackwener/OpenCLI","slug":"coingecko-limit-must-be-a-positive-integer-35e853","errorCode":null,"errorMessage":"coingecko limit must be a positive integer","messagePattern":"coingecko limit must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/coingecko/exchanges.js","lineNumber":25,"sourceCode":"import { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\ncli({\n    site: 'coingecko',\n    name: 'exchanges',\n    access: 'read',\n    description: 'Top crypto exchanges by 24h BTC trading volume',\n    domain: 'api.coingecko.com',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'limit', type: 'int', default: 20, help: 'Number of exchanges (1-250, CoinGecko per_page upper bound)' },\n        { name: 'page', type: 'int', default: 1, help: 'Page number (1-based)' },\n    ],\n    columns: ['rank', 'id', 'name', 'trustScore', 'volume24hBtc', 'country', 'yearEstablished', 'url'],\n    func: async (args) => {\n        const limit = Number(args.limit ?? 20);\n        if (!Number.isInteger(limit) || limit <= 0) {\n            throw new ArgumentError('coingecko limit must be a positive integer');\n        }\n        if (limit > 250) {\n            throw new ArgumentError('coingecko limit must be <= 250 (per_page upper bound)');\n        }\n        const page = Number(args.page ?? 1);\n        if (!Number.isInteger(page) || page <= 0) {\n            throw new ArgumentError('coingecko page must be a positive integer');\n        }\n        const url = new URL('https://api.coingecko.com/api/v3/exchanges');\n        url.searchParams.set('per_page', String(limit));\n        url.searchParams.set('page', String(page));\n        let resp;\n        try {\n            resp = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0' } });\n        }\n        catch (err) {\n            throw new CommandExecutionError(`coingecko exchanges request failed: ${err?.message ?? err}`);\n        }","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coingecko/exchanges.js#L7-L43","documentation":"ArgumentError thrown by the coingecko exchanges command when the --limit argument is not a positive integer (Number() coercion fails, is fractional, NaN, or <= 0). The library validates arguments up-front so the API call is never made with an invalid per_page.","triggerScenarios":"Passing --limit 0, --limit -5, --limit abc, --limit 2.5, or an empty string that coerces to NaN when running the exchanges command.","commonSituations":"Shell quoting mistakes (empty --limit ''), copy-pasted fractional values, scripts computing a limit with parseFloat on non-numeric input, default omitted and a placeholder left in a config.","solutions":["Pass a whole number >= 1, e.g. --limit 20.","If the value comes from a script/config, coerce and validate with Number.isInteger(Number(v)) && Number(v) > 0 before invoking.","Check shell quoting so the flag isn't empty or split.","Omit --limit entirely to use the default of 20."],"exampleFix":"// before\nrunCli(['coingecko', 'exchanges', '--limit', 'all']);\n// after\nconst limit = 100;\nrunCli(['coingecko', 'exchanges', '--limit', String(limit)]);","handlingStrategy":"validation","validationCode":"const n = Number(limit);\nif (!Number.isInteger(n) || n <= 0) {\n  throw new TypeError(`limit must be a positive integer, got ${JSON.stringify(limit)}`);\n}","typeGuard":"function isValidLimit(v) {\n  const n = Number(v);\n  return Number.isInteger(n) && n > 0 && n <= 250;\n}","tryCatchPattern":"try {\n  return await runCli(['coingecko', 'exchanges', '--limit', String(limit)]);\n} catch (err) {\n  if (String(err.message).includes('limit must be a positive integer')) {\n    console.warn(`Invalid limit \"${limit}\"; falling back to default 20.`);\n    return runCli(['coingecko', 'exchanges']);\n  }\n  throw err;\n}","preventionTips":["Validate limit with Number.isInteger && > 0 before invoking the CLI.","Never pass empty strings — check shell quoting around --limit.","Parse config values with strict integer parsing, not parseFloat.","Omit --limit to use the built-in default of 20."],"tags":["argument-validation","user-input","cli","coingecko"],"backgroundTag":"invalid-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}