{"record":{"id":"8b57786cc3fa26f2","repo":"jackwener/OpenCLI","slug":"limit-must-be-a-positive-integer-got-json-str","errorCode":null,"errorMessage":"--limit must be a positive integer, got ${JSON.stringify(kwargs.limit)}","messagePattern":"--limit must be a positive integer, got (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/douyin/hashtag.js","lineNumber":25,"sourceCode":"}\n\nfunction requireListField(res, field, action) {\n    if (!isPlainObject(res)) {\n        throw new CommandExecutionError(`douyin hashtag ${action}: API returned malformed payload`);\n    }\n    const list = res[field];\n    if (list === undefined || list === null) return [];\n    if (!Array.isArray(list)) {\n        throw new CommandExecutionError(`douyin hashtag ${action}: API returned malformed \"${field}\"`);\n    }\n    return list;\n}\n\nfunction validateHashtagArgs(kwargs) {\n    const action = kwargs.action;\n    const limit = Number(kwargs.limit ?? 10);\n    if (!Number.isInteger(limit) || limit < 1) {\n        throw new ArgumentError(`--limit must be a positive integer, got ${JSON.stringify(kwargs.limit)}`);\n    }\n    if (action === 'search') {\n        const keyword = String(kwargs.keyword ?? '').trim();\n        if (!keyword) {\n            throw new ArgumentError('douyin hashtag search 需要 --keyword <关键词>', '示例: opencli douyin hashtag search --keyword 美食');\n        }\n        return;\n    }\n    if (action === 'suggest') {\n        const cover = String(kwargs.cover ?? '').trim();\n        if (!cover) {\n            throw new ArgumentError('douyin hashtag suggest 需要 --cover <cover_uri>', 'suggest 基于已上传的视频封面做 AI 推荐, 不是关键词搜索. 关键词搜索请用 `douyin hashtag search --keyword <词>`.');\n        }\n    }\n}\n\ncli({\n    site: 'douyin',","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/hashtag.js#L7-L43","documentation":"validateHashtagArgs coerces kwargs.limit with Number(limit ?? 10) and requires a positive integer. Non-integer, zero, negative, or NaN values produce an ArgumentError echoing the JSON-encoded input so the bad value is visible.","triggerScenarios":"Passing `--limit 0`, `--limit -5`, `--limit abc`, `--limit 2.5`, or `--limit \"\"` to `douyin hashtag list/search/suggest`. Number('') is 0 and Number(undefined) falls back to 10, so empty strings and garbage both fail here.","commonSituations":"Shell scripts with unquoted/empty variables (`--limit $LIMIT` where LIMIT is unset), copy-pasted fractional values, or users assuming limit is optional-but-zero means unlimited.","solutions":["Pass a positive integer, e.g. `--limit 10`","Fix the script variable: use `${LIMIT:-10}` or validate before invoking","Omit --limit entirely to use the default of 10"],"exampleFix":"// before\nopencli douyin hashtag search --keyword 美食 --limit $LIMIT  // LIMIT empty → 0\n// after\nopencli douyin hashtag search --keyword 美食 --limit \"${LIMIT:-10}\"","handlingStrategy":"validation","validationCode":"const limit = Number(process.argv.limit ?? 10);\nif (!Number.isInteger(limit) || limit < 1) throw new Error(`--limit must be a positive integer, got ${limit}`);","typeGuard":"const isValidLimit = (v) => Number.isInteger(Number(v)) && Number(v) >= 1;","tryCatchPattern":"try {\n  await cli.hashtag({ action: 'search', keyword, limit });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('--limit')) {\n    await cli.hashtag({ action: 'search', keyword, limit: 10 }); // default\n  } else throw e;\n}","preventionTips":["Quote and default shell variables: --limit \"${LIMIT:-10}\"","Never pass user input to --limit without integer validation","Omit --limit to accept the built-in default of 10"],"tags":["validation","argument-error","cli-input"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}