jackwener/OpenCLI · error · ArgumentError

--timeout must be a positive integer (seconds)

Error message

--timeout must be a positive integer (seconds)

What it means

normalizeTimeout in utils.js throws an ArgumentError when the --timeout value is not an integer >= 1 (seconds). The value passes through Number(), so NaN, floats, 0, negatives, and non-numeric strings all fail the Number.isInteger/limit check.

Source

Thrown at clis/trae-cn/utils.js:32

  'shred',
  'dd',
  'truncate',
  'kill',
  'chmod',
  'mv',
  'copy',
  'move',
  'Set-Content',
  'Out-File',
  'mkfs',
  'git force/delete/hard/filter/rebase operations',
  'destructive database commands',
];

export function normalizeTimeout(value, fallback = 60) {
  const timeout = value === undefined || value === null ? fallback : Number(value);
  if (!Number.isInteger(timeout) || timeout < 1) {
    throw new ArgumentError('--timeout must be a positive integer (seconds)');
  }
  return timeout;
}

export function normalizeLimit(value, fallback = 20) {
  const limit = value === undefined || value === null ? fallback : Number(value);
  if (!Number.isInteger(limit) || limit < 1 || limit > 200) {
    throw new ArgumentError('--limit must be an integer between 1 and 200');
  }
  return limit;
}

export function normalizeMaxChars(value, fallback = 6000) {
  const maxChars = value === undefined || value === null ? fallback : Number(value);
  if (!Number.isInteger(maxChars) || maxChars < 0 || maxChars > 1_000_000) {
    throw new ArgumentError('--max-chars must be an integer between 0 and 1000000');
  }
  return maxChars;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a positive whole number of seconds, e.g. --timeout 60.
  2. Omit --timeout to use the 60-second default.
  3. Fix shell scripts so empty variables aren't passed: use ${VAR:-60} or skip the flag when unset.
  4. Convert minutes to seconds yourself: --timeout 120 for 2 minutes.

Example fix

// before
opencli trae-cn ask "hi" --timeout "$TIMEOUT"   # TIMEOUT empty -> 0
// after
opencli trae-cn ask "hi" --timeout "${TIMEOUT:-60}"
Defensive patterns

Strategy: validation

Validate before calling

function assertTimeout(v, fallback = 60) {
  const t = v === undefined || v === null ? fallback : Number(v);
  if (!Number.isInteger(t) || t < 1) throw new Error(`Invalid --timeout: ${JSON.stringify(v)}; use a positive integer (seconds)`);
  return t;
}

Type guard

function isValidTimeout(v) {
  return typeof v === 'number' ? Number.isInteger(v) && v >= 1 : v === undefined || v === null || String(v).trim() !== '' && Number.isInteger(Number(v)) && Number(v) >= 1;
}

Try / catch

try {
  await runCommand(['--timeout', String(userTimeout)]);
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('--timeout')) {
    console.error('Falling back to default timeout 60s');
    return runCommand([]);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running any trae-cn command with `--timeout 0`, `--timeout -5`, `--timeout 2.5`, `--timeout abc`, or `--timeout ""` (empty string coerces to 0).

Common situations: Scripts interpolating empty/unset variables into --timeout; typo'd units like `--timeout 90s` or `--timeout 1.5m`; assuming 0 means 'no timeout'.

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