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 image command validates --timeout before generating; it must be an integer >= 1 (seconds) or ArgumentError('--timeout must be a positive integer (seconds)') is thrown. The timeout bounds how long the command waits for Gemini to produce an image after the prompt is sent. Validation happens up front, before any chat is started or message sent.

Source

Thrown at clis/gemini/image.js:84

    navigateBefore: false,
    defaultFormat: 'plain',
    args: [
        { name: 'prompt', positional: true, required: true, help: 'Image prompt to send to Gemini' },
        { name: 'rt', default: '1:1', help: 'Ratio shorthand for aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3)' },
        { name: 'st', default: '', help: 'Style shorthand, e.g. anime, icon, watercolor' },
        { name: 'op', default: '~/tmp/gemini-images', help: 'Output directory shorthand' },
        { name: 'sd', type: 'boolean', default: false, help: 'Skip download shorthand; only show Gemini page link' },
        { name: 'timeout', type: 'int', required: false, default: 240, help: 'Max seconds for the overall command (default: 240)' },
    ],
    columns: ['status', 'file', 'link'],
    func: async (page, kwargs) => {
        const prompt = kwargs.prompt;
        const ratio = normalizeRatio(String(kwargs.rt ?? '1:1'));
        const style = String(kwargs.st ?? '').trim();
        const outputDir = resolveOutputDir(kwargs.op);
        const timeout = kwargs.timeout;
        if (!Number.isInteger(timeout) || timeout < 1) {
            throw new ArgumentError('--timeout must be a positive integer (seconds)');
        }
        const startFresh = true;
        const skipDownloadRaw = kwargs.sd;
        const skipDownload = skipDownloadRaw === '' || skipDownloadRaw === true || normalizeBooleanFlag(skipDownloadRaw);
        const effectivePrompt = buildImagePrompt(prompt, {
            ratio,
            style: style || undefined,
        });
        if (startFresh)
            await startNewGeminiChat(page);
        const beforeUrls = await getGeminiVisibleImageUrls(page);
        await sendGeminiMessage(page, effectivePrompt);
        const urls = await waitForGeminiImages(page, beforeUrls, timeout);
        const link = await currentGeminiLink(page);
        if (!urls.length) {
            throw new EmptyResultError('gemini image', `No generated image was detected. Open ${link} and check whether Gemini produced one.`);
        }
        if (skipDownload) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass --timeout as a plain positive integer, e.g. --timeout 90 (image generation can be slow, prefer generous values)
  2. Convert any units to whole seconds before invoking
  3. Guard script-interpolated values: default to an integer when unset, e.g. TIMEOUT="${TIMEOUT:-120}"
  4. Round computed values and re-check Number.isInteger in wrappers

Example fix

// before
opencli gemini image --prompt "a cat" --timeout 1.5m
// after
opencli gemini image --prompt "a cat" --timeout 90
Defensive patterns

Strategy: validation

Validate before calling

const t = Number(process.env.IMG_TIMEOUT ?? 120);
if (!Number.isInteger(t) || t < 1) throw new Error('--timeout must be a positive integer (seconds)');

Type guard

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

Try / catch

try {
  await run(['gemini','image','--prompt',p,'--timeout',String(t)]);
} catch (e) {
  if (String(e.message).includes('--timeout must be a positive integer')) {
    console.error('Pass --timeout as whole seconds, e.g. --timeout 120');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `opencli gemini image` with --timeout omitted, fractional (e.g. 1.5), zero, negative, or non-numeric ('60s', 'minute').

Common situations: Duration strings with units pasted from docs; computed float from config (e.g. seconds*1.5); unset env var interpolated into the flag; YAML/JSON pipeline quoting the number as a string with characters like 'ms'.

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/14c9a12201809251. Report an issue: GitHub.