{"record":{"id":"586a9bb06baf34cf","repo":"jackwener/OpenCLI","slug":"timeout-must-be-a-positive-integer-586a9b","errorCode":null,"errorMessage":"timeout must be a positive integer","messagePattern":"timeout must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/qwen/image.js","lineNumber":121,"sourceCode":"    navigateBefore: false,\n    defaultFormat: 'plain',\n    args: [\n        { name: 'prompt', required: true, positional: true, help: 'Image prompt to send' },\n        { name: 'op', default: '~/Pictures/qianwen', help: 'Output directory' },\n        { name: 'new', type: 'boolean', default: true, help: 'Start a new chat before generating (default: true)' },\n        { name: 'sd', type: 'boolean', default: false, help: 'Skip download; only show the Qianwen link' },\n        { name: 'timeout', type: 'int', default: 180, help: 'Max seconds to wait for the image response' },\n    ],\n    columns: ['Status', 'File', 'Link'],\n    func: async (page, kwargs) => {\n        const prompt = String(kwargs.prompt || '').trim();\n        if (!prompt) throw new ArgumentError('prompt is required');\n        const outputDir = String(kwargs.op || '~/Pictures/qianwen').replace(/^~\\//, `${os.homedir()}/`);\n        const startFresh = normalizeBooleanFlag(kwargs.new, true);\n        const skipDownload = normalizeBooleanFlag(kwargs.sd, false);\n        const timeout = Number(kwargs.timeout ?? 180);\n        if (!Number.isInteger(timeout) || timeout <= 0) {\n            throw new ArgumentError('timeout must be a positive integer');\n        }\n\n        await ensureOnQianwen(page);\n        await dismissLoginModal(page);\n        if (startFresh) {\n            await startNewChat(page);\n            await dismissLoginModal(page);\n        }\n        await setFeatureToggle(page, 'image', true);\n        await page.wait(0.5);\n\n        const send = await sendMessage(page, prompt);\n        if (!send?.ok) {\n            if (await hasLoginGate(page)) throw authRequired();\n            throw new CommandExecutionError(send?.reason || 'Failed to send Qianwen image prompt');\n        }\n\n        // Grab the newest assistant bubble id after send by polling briefly","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/qwen/image.js#L103-L139","documentation":"clis/qwen/image.js throws ArgumentError('timeout must be a positive integer') when the `timeout` kwarg, coerced via Number(kwargs.timeout ?? 180), is not an integer or is <= 0. The library validates this up front because the value is passed to waitForImageUrls as a wait budget in seconds. The default is 180 when the option is omitted.","triggerScenarios":"Calling the qianwen image command with --timeout set to a non-numeric string (e.g. '30s', 'abc'), a float (e.g. 2.5), zero, or a negative number. Number() coercion means '' becomes 0 and '0' becomes 0, both rejected.","commonSituations":"Users writing 'timeout=90s' or '1.5m' expecting duration parsing; shell variables that are empty or unset producing 0; scripts passing fractional defaults; copy-pasted configs where timeout was quoted with units.","solutions":["Pass timeout as a plain positive integer in seconds, e.g. --timeout 300","Remove units or convert them yourself before invoking (90s -> 90)","Check the resolved value: echo the kwarg; if it is empty or '0', fix the source script/config","Omit --timeout entirely to use the built-in default of 180 seconds"],"exampleFix":"// before\nnode cli.js qwen image --prompt 'a cat' --timeout 90s\n// after\nnode cli.js qwen image --prompt 'a cat' --timeout 90","handlingStrategy":"validation","validationCode":"function isValidTimeout(v) {\n  const n = Number(v);\n  return Number.isInteger(n) && n > 0;\n}\nconst timeout = process.argv.timeout ?? 180;\nif (!isValidTimeout(timeout)) throw new Error(`timeout must be a positive integer, got: ${JSON.stringify(timeout)}`);","typeGuard":"const isPositiveInt = (v) => typeof v === 'number' && Number.isInteger(v) && v > 0;","tryCatchPattern":"try {\n  await runImageCommand({ prompt, timeout });\n} catch (e) {\n  if (e instanceof ArgumentError && /timeout must be a positive integer/.test(e.message)) {\n    console.error('Fix: pass --timeout as whole seconds, e.g. --timeout 300');\n  } else throw e;\n}","preventionTips":["Always pass timeout as plain integer seconds, never with units like '90s'","Rely on the built-in default (180) unless you have a reason to override","Validate shell variables feeding the flag are non-empty integers","Centralize timeout parsing in one helper that rejects non-integers early"],"tags":["validation","arguments","timeout"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}