jackwener/OpenCLI · error · ArgumentError
--timeout must be a positive integer (seconds)
Error message
--timeout must be a positive integer (seconds)
What it means
The codex ask command validates its --timeout flag inline before opening a conversation: it must be an integer >= 1 (seconds). Otherwise it throws this ArgumentError, since a zero/negative/NaN timeout cannot bound the response wait meaningfully.
Source
Thrown at clis/codex/ask.js:22
export const askCommand = cli({
site: 'codex',
name: 'ask',
access: 'write',
description: 'Send a prompt to the current or selected Codex conversation and wait for the AI response',
domain: 'localhost',
strategy: Strategy.UI,
browser: true,
args: [
{ name: 'text', required: true, positional: true, help: 'Prompt to send' },
{ name: 'timeout', type: 'int', required: false, help: 'Max seconds to wait for response (default: 60)', default: 60 },
...conversationSelectionArgs,
],
columns: ['Role', 'Project', 'Conversation', 'Text'],
func: async (page, kwargs) => {
const text = kwargs.text;
const timeout = kwargs.timeout;
if (!Number.isInteger(timeout) || timeout < 1) {
throw new ArgumentError('--timeout must be a positive integer (seconds)');
}
const selected = await openCodexConversation(page, kwargs);
// Snapshot the current content length before sending
const beforeLen = await page.evaluate(`
(function() {
const turns = document.querySelectorAll('[data-content-search-turn-key]');
return turns.length;
})()
`);
// Inject and send
const injected = await page.evaluate(`
(function(text) {
const editables = Array.from(document.querySelectorAll('[contenteditable="true"]'));
const composer = editables.length > 0 ? editables[editables.length - 1] : document.querySelector('textarea');
if (!composer) return false;
composer.focus();
document.execCommand('insertText', false, text);
return true;View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a positive whole number of seconds, e.g. --timeout 30
- Fix env/config defaults so they are integers >= 1
- Strip unit suffixes and validate before invoking the CLI
Example fix
// before
await codexAsk({ text: 'hi', timeout: Number(process.env.T || 0) }); // throws
// after
await codexAsk({ text: 'hi', timeout: Number(process.env.T || 30) }); // >= 1 Defensive patterns
Strategy: validation
Validate before calling
const timeout = Number(process.env.TIMEOUT);
if (!Number.isInteger(timeout) || timeout < 1) {
throw new Error('--timeout must be a positive integer (seconds)');
} Type guard
function isValidTimeout(v) {
return Number.isInteger(v) && v >= 1;
} Try / catch
try {
await codexAsk({ text, timeout });
} catch (e) {
if (e instanceof ArgumentError && e.message.includes('--timeout must be a positive integer')) {
console.error('Pass seconds, e.g. --timeout 30');
process.exitCode = 2;
} else throw e;
} Prevention
- Default timeouts to a sane positive integer (e.g. 30)
- Validate env-derived values with Number.isInteger before passing
- Keep units documented (seconds, not milliseconds)
- Avoid 0/negative sentinels for timeout flags
When it happens
Trigger: `opencli codex ask --timeout 0`, a negative value, a float, or an unset/empty env-derived value that becomes NaN or 0.
Common situations: Treating 0 as 'unlimited', passing milliseconds (60000) expecting seconds semantics is fine but 0.5 or '' is not, config defaults of 0.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
- archive search query must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/eba49986ac2beaee.
Report an issue: GitHub.