{"record":{"id":"a903008ffd25ffe9","repo":"jackwener/OpenCLI","slug":"timeout-must-be-a-positive-integer-seconds-a90300","errorCode":null,"errorMessage":"--timeout must be a positive integer (seconds)","messagePattern":"--timeout must be a positive integer \\(seconds\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/gemini/deep-research.js","lineNumber":40,"sourceCode":"    description: 'Start a Gemini Deep Research run and confirm it',\n    domain: GEMINI_DOMAIN,\n    strategy: Strategy.COOKIE,\n    browser: true,\n    siteSession: 'persistent',\n    navigateBefore: false,\n    defaultFormat: 'plain',\n    args: [\n        { name: 'prompt', positional: true, required: true, help: 'Prompt to send' },\n        { name: 'timeout', type: 'int', required: false, help: 'Max seconds for the overall command (default: 180; confirm-wait clamps internally to 6-20s)', default: 180 },\n        { name: 'tool', required: false, help: 'Override tool label (default: Deep Research)' },\n        { name: 'confirm', required: false, help: 'Override confirm button label (default: Start research)' },\n    ],\n    columns: ['status', 'url'],\n    func: async (page, kwargs) => {\n        const prompt = kwargs.prompt;\n        const timeout = kwargs.timeout;\n        if (!Number.isInteger(timeout) || timeout < 1) {\n            throw new ArgumentError('--timeout must be a positive integer (seconds)');\n        }\n        const submitTimeout = Math.min(Math.max(timeout, 6), 20);\n        await startNewGeminiChat(page);\n        const toolLabels = resolveGeminiLabels(kwargs.tool, GEMINI_DEEP_RESEARCH_DEFAULT_TOOL_LABELS);\n        const confirmLabels = resolveGeminiLabels(kwargs.confirm, GEMINI_DEEP_RESEARCH_DEFAULT_CONFIRM_LABELS);\n        const toolMatched = await selectGeminiTool(page, toolLabels);\n        if (!toolMatched) {\n            const url = await getCurrentGeminiUrl(page);\n            return [{ status: 'tool-not-found', url }];\n        }\n        let baseline = await readGeminiSnapshot(page);\n        await sendGeminiMessage(page, prompt);\n        let submitted = await waitForGeminiSubmission(page, baseline, submitTimeout);\n        if (!submitted) {\n            // Retry once when submit did not stick (e.g. composer swallowed Enter/click in this UI state).\n            await selectGeminiTool(page, toolLabels);\n            baseline = await readGeminiSnapshot(page);\n            await sendGeminiMessage(page, prompt);","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gemini/deep-research.js#L22-L58","documentation":"The gemini deep-research command requires --timeout to be an integer >= 1 (seconds) and throws ArgumentError otherwise. The value is clamped later via Math.min(Math.max(timeout, 6), 20), so only integers within valid bounds pass the initial check. This validates user input before any browser automation begins.","triggerScenarios":"Running `opencli gemini deep-research` with --timeout missing (undefined), fractional (2.5), zero, negative, or a non-numeric string such as 'soon' or '45s'.","commonSituations":"Forgetting the flag entirely; typing a duration with units; a CI config template leaving --timeout empty; passing a float from a computed value without Math.floor/round.","solutions":["Supply --timeout as an integer >= 1, e.g. --timeout 15 (practical effective range is clamped to 6-20 seconds for submit wait)","Coerce computed values with Math.round before passing","If the flag is conditionally built in a script, guard against emitting an empty '--timeout' with no value","Verify the wrapper/parser passes the raw number, not a quoted string"],"exampleFix":"// before\nconst timeout = '2.5';\nawait run(['gemini', 'deep-research', '--prompt', p, '--timeout', timeout]);\n// after\nconst timeout = Math.max(1, Math.round(Number('2.5')));\nawait run(['gemini', 'deep-research', '--prompt', p, '--timeout', String(timeout)]);","handlingStrategy":"validation","validationCode":"const t = Number(rawTimeout);\nif (!Number.isInteger(t) || t < 1) throw new Error('timeout must be a positive integer (seconds)');","typeGuard":"const isPositiveInt = (v) => Number.isInteger(v) && v >= 1;","tryCatchPattern":"try {\n  await run(['gemini','deep-research','--prompt',p,'--timeout',String(t)]);\n} catch (e) {\n  if (String(e.message).includes('positive integer')) {\n    t = Math.max(1, Math.round(Number(t) || 10));\n  } else throw e;\n}","preventionTips":["Coerce and round computed timeouts before passing","Never emit an empty '--timeout' flag; always pair flag with a valid value","Remember the effective submit wait is clamped to 6-20s, so pick a value in that range"],"tags":["validation","argument-error","cli","timeout"],"backgroundTag":"invalid-cli-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}