{"record":{"id":"bd9c45ed97968c90","repo":"jackwener/OpenCLI","slug":"timeout-must-be-a-positive-integer-seconds-bd9c45","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-result.js","lineNumber":61,"sourceCode":"    description: 'Export Deep Research report URL from a Gemini conversation',\n    domain: GEMINI_DOMAIN,\n    strategy: Strategy.COOKIE,\n    browser: true,\n    siteSession: 'persistent',\n    navigateBefore: false,\n    defaultFormat: 'plain',\n    args: [\n        { name: 'query', positional: true, required: false, help: 'Conversation title or URL (optional; defaults to latest conversation)' },\n        { name: 'match', required: false, default: 'contains', choices: ['contains', 'exact'], help: 'Match mode' },\n        { name: 'timeout', type: 'int', required: false, default: 120, help: 'Max seconds to wait for Docs export (default: 120)' },\n    ],\n    columns: ['response'],\n    func: async (page, kwargs) => {\n        const query = String(kwargs.query ?? '').trim();\n        const matchMode = parseGeminiTitleMatchMode(kwargs.match);\n        const timeoutSeconds = kwargs.timeout;\n        if (!Number.isInteger(timeoutSeconds) || timeoutSeconds < 1) {\n            throw new ArgumentError('--timeout must be a positive integer (seconds)');\n        }\n        if (!matchMode) {\n            return [{ response: 'Invalid match mode. Use contains or exact.' }];\n        }\n        const state = await getGeminiPageState(page);\n        if (state.isSignedIn === false) {\n            return [{ response: 'Not signed in to Gemini.' }];\n        }\n        const conversationUrl = parseGeminiConversationUrl(query);\n        if (conversationUrl) {\n            await page.goto(conversationUrl, { waitUntil: 'load', settleMs: 2500 });\n            await page.wait(1);\n            await waitForGeminiTranscript(page);\n            return [{ response: await resolveDeepResearchExportResponse(page, timeoutSeconds) }];\n        }\n        const conversations = await getGeminiConversationList(page);\n        const picked = resolveGeminiConversationForQuery(conversations, query, matchMode);\n        if (picked?.Url) {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gemini/deep-research-result.js#L43-L79","documentation":"The gemini deep-research-result CLI command validates its --timeout option and throws ArgumentError when it is not an integer >= 1 (seconds). The library intentionally rejects fractional, zero, negative, and non-numeric values because the timeout is used directly as a wait duration in seconds. This fail-fast validation prevents silent hangs or invalid browser waits later in the command.","triggerScenarios":"Calling `opencli gemini deep-research-result` with --timeout given as a non-integer (e.g. 2.5), a string (e.g. '30s' or 'abc'), zero, a negative number, or omitted in a way that yields undefined/null.","commonSituations":"Passing CLI flags with units ('30s', '1m') instead of plain seconds; a wrapper script interpolating an empty or undefined variable into --timeout; copying a fractional default like 1.5 from docs; shell quoting issues turning the value into a string.","solutions":["Pass --timeout as a plain positive integer in seconds, e.g. --timeout 30","If the value comes from a variable/env var, ensure it is set, numeric, and integer-valued before invoking","Remove any unit suffix or decimal portion (convert 90s -> 90, 1.5 -> 2)","Check your arg parser is not passing the flag value as a string; coerce with Number() and verify Number.isInteger"],"exampleFix":"// before\nopencli gemini deep-research-result --query \"...\" --timeout 30s\n// after\nopencli gemini deep-research-result --query \"...\" --timeout 30","handlingStrategy":"validation","validationCode":"function isValidTimeout(t){ return Number.isInteger(t) && t >= 1; }\nconst timeout = Number(process.env.TIMEOUT);\nif (!isValidTimeout(timeout)) throw new Error('--timeout must be a positive integer (seconds)');","typeGuard":"function isPositiveInt(v){ return typeof v === 'number' && Number.isInteger(v) && v >= 1; }","tryCatchPattern":"try {\n  await run(['gemini','deep-research-result','--query',q,'--timeout',String(timeout)]);\n} catch (e) {\n  if (String(e.message).includes('--timeout must be a positive integer')) {\n    console.error('Fix --timeout: pass an integer >= 1 (seconds), no units.');\n  } else throw e;\n}","preventionTips":["Always pass timeouts as bare integers in seconds, never with unit suffixes","Default unset env/config values to a sane integer before invoking","Validate with Number.isInteger(value) && value >= 1 in wrapper scripts"],"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"}