jackwener/OpenCLI · error · ArgumentError

ocr-wait-seconds must be a non-negative integer: ${raw}

Error message

ocr-wait-seconds must be a non-negative integer: ${raw}

What it means

parseOcrWaitSeconds reads the optional ocr-wait-seconds setting (default '8') and requires it to be all digits (^\d+$), i.e. a non-negative integer. Negatives, decimals, negatives-of-zero variants, empty strings, or non-numeric text throw this ArgumentError; the validated value is returned as a Number.

Source

Thrown at clis/mercury/utils.js:84

    const date = requireString(kwargs, 'date');
    const match = date.match(/^(\d{4})-(\d{2})-(\d{2})$/);
    if (!match) {
        throw new ArgumentError(`Date must be YYYY-MM-DD: ${date}`);
    }
    const year = Number(match[1]);
    const month = Number(match[2]);
    const day = Number(match[3]);
    const parsed = new Date(Date.UTC(year, month - 1, day));
    if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {
        throw new ArgumentError(`Date must be a real calendar date: ${date}`);
    }
    return date;
}

function parseOcrWaitSeconds(kwargs) {
    const raw = optionalString(kwargs, 'ocr-wait-seconds', '8');
    if (!/^\d+$/.test(raw)) {
        throw new ArgumentError(`ocr-wait-seconds must be a non-negative integer: ${raw}`);
    }
    return Number(raw);
}

export function normalizeReimbursementInput(kwargs) {
    return {
        receipt: parseReceiptPath(kwargs),
        amount: parseAmount(kwargs),
        currency: parseCurrency(kwargs),
        date: parseDate(kwargs),
        merchant: requireString(kwargs, 'merchant'),
        category: optionalString(kwargs, 'category', 'Marketing & Advertising'),
        notes: requireString(kwargs, 'notes'),
        ocrWaitSeconds: parseOcrWaitSeconds(kwargs),
        closeAfterReview: optionalBoolean(kwargs, 'close-after-review', false),
    };
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a plain non-negative integer: --ocr-wait-seconds 30.
  2. Convert durations to seconds yourself (1m -> 60) before passing.
  3. Restore the default by omitting the option (defaults to 8 seconds).
  4. If sourced from env, verify the variable is set and contains digits: echo "$OCR_WAIT".

Example fix

// before
--ocr-wait-seconds "1m"
// after
--ocr-wait-seconds "60"
Defensive patterns

Strategy: validation

Validate before calling

function isValidWaitSeconds(v) {
  return /^\d+$/.test(String(v));
}

Try / catch

try {
  await reimburse({ 'ocr-wait-seconds': wait });
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('ocr-wait-seconds')) {
    console.error('Provide a whole number of seconds, e.g. --ocr-wait-seconds 30');
  } else throw e;
}

Prevention

When it happens

Trigger: --ocr-wait-seconds '-1', '2.5', 'eight', '', '+8', or '8s' — anything not purely digits.

Common situations: Users expressing durations with units ('30s', '1m'); copying decimal timeouts from config files; environment placeholders that failed to expand leaving empty or templated text; negative values intended as 'no wait'.

Related errors


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