jackwener/OpenCLI · error · ArgumentError

--timeout must be a positive integer (seconds)

Error message

--timeout must be a positive integer (seconds)

What it means

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.

Source

Thrown at clis/gemini/deep-research.js:40

    description: 'Start a Gemini Deep Research run and confirm it',
    domain: GEMINI_DOMAIN,
    strategy: Strategy.COOKIE,
    browser: true,
    siteSession: 'persistent',
    navigateBefore: false,
    defaultFormat: 'plain',
    args: [
        { name: 'prompt', positional: true, required: true, help: 'Prompt to send' },
        { name: 'timeout', type: 'int', required: false, help: 'Max seconds for the overall command (default: 180; confirm-wait clamps internally to 6-20s)', default: 180 },
        { name: 'tool', required: false, help: 'Override tool label (default: Deep Research)' },
        { name: 'confirm', required: false, help: 'Override confirm button label (default: Start research)' },
    ],
    columns: ['status', 'url'],
    func: async (page, kwargs) => {
        const prompt = kwargs.prompt;
        const timeout = kwargs.timeout;
        if (!Number.isInteger(timeout) || timeout < 1) {
            throw new ArgumentError('--timeout must be a positive integer (seconds)');
        }
        const submitTimeout = Math.min(Math.max(timeout, 6), 20);
        await startNewGeminiChat(page);
        const toolLabels = resolveGeminiLabels(kwargs.tool, GEMINI_DEEP_RESEARCH_DEFAULT_TOOL_LABELS);
        const confirmLabels = resolveGeminiLabels(kwargs.confirm, GEMINI_DEEP_RESEARCH_DEFAULT_CONFIRM_LABELS);
        const toolMatched = await selectGeminiTool(page, toolLabels);
        if (!toolMatched) {
            const url = await getCurrentGeminiUrl(page);
            return [{ status: 'tool-not-found', url }];
        }
        let baseline = await readGeminiSnapshot(page);
        await sendGeminiMessage(page, prompt);
        let submitted = await waitForGeminiSubmission(page, baseline, submitTimeout);
        if (!submitted) {
            // Retry once when submit did not stick (e.g. composer swallowed Enter/click in this UI state).
            await selectGeminiTool(page, toolLabels);
            baseline = await readGeminiSnapshot(page);
            await sendGeminiMessage(page, prompt);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Supply --timeout as an integer >= 1, e.g. --timeout 15 (practical effective range is clamped to 6-20 seconds for submit wait)
  2. Coerce computed values with Math.round before passing
  3. If the flag is conditionally built in a script, guard against emitting an empty '--timeout' with no value
  4. Verify the wrapper/parser passes the raw number, not a quoted string

Example fix

// before
const timeout = '2.5';
await run(['gemini', 'deep-research', '--prompt', p, '--timeout', timeout]);
// after
const timeout = Math.max(1, Math.round(Number('2.5')));
await run(['gemini', 'deep-research', '--prompt', p, '--timeout', String(timeout)]);
Defensive patterns

Strategy: validation

Validate before calling

const t = Number(rawTimeout);
if (!Number.isInteger(t) || t < 1) throw new Error('timeout must be a positive integer (seconds)');

Type guard

const isPositiveInt = (v) => Number.isInteger(v) && v >= 1;

Try / catch

try {
  await run(['gemini','deep-research','--prompt',p,'--timeout',String(t)]);
} catch (e) {
  if (String(e.message).includes('positive integer')) {
    t = Math.max(1, Math.round(Number(t) || 10));
  } else throw e;
}

Prevention

When it happens

Trigger: Running `opencli gemini deep-research` with --timeout missing (undefined), fractional (2.5), zero, negative, or a non-numeric string such as 'soon' or '45s'.

Common situations: 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.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/a903008ffd25ffe9. Report an issue: GitHub.