affaan-m/ECC · error · Error

timeout is outside the 10-120 second safety range

Error message

timeout is outside the 10-120 second safety range

What it means

runReview validates the requested Codex subprocess timeout before spawning the CLI. Node spawnSync accepts any value, but this library deliberately confines timeouts to 10-120 seconds so a review cannot hang forever or kill Codex before it starts producing output. If options.timeoutMs is below 10000 or above MAX_TIMEOUT_MS (120000), the call is rejected before any process is started.

Solutions

  1. Set timeoutMs to a value between 10000 and 120000 milliseconds (e.g. 60000).
  2. Clamp user-supplied values: timeoutMs = Math.min(Math.max(Number(timeoutMs) || 60000, 10000), 120000).
  3. If a review needs more than 120s, split the prompt into smaller review packets instead of raising the timeout.
  4. Ensure timeoutMs is a number, not a string from CLI args (use Number() before calling).

Example fix

// before
await runReview({ prompt, consent: true, timeoutMs: 5000 });
// after
await runReview({ prompt, consent: true, timeoutMs: 60_000 }); // within 10s-120s
Defensive patterns

Strategy: validation

Validate before calling

function isValidTimeout(ms) {
  return typeof ms === 'number' && Number.isFinite(ms) && ms >= 10_000 && ms <= 120_000;
}
if (!isValidTimeout(opts.timeoutMs)) throw new RangeError('timeoutMs must be 10000-120000 ms');

Type guard

const isTimeoutMs = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 10_000 && v <= 120_000;

Try / catch

try {
  await runReview(options);
} catch (e) {
  if (e.message.includes('safety range')) {
    options.timeoutMs = 60_000;
    await runReview(options);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling runReview({ ..., timeoutMs: 5000 }) or runReview({ ..., timeoutMs: 300000 }) — any value outside the inclusive 10000..120000 ms window, including undefined coerced to NaN by the comparison.

Common situations: Developer sets a 5-second timeout expecting a fast check; developer reuses a general-purpose 10-minute timeout constant from another tool; timeoutMs passed as a string or omitted so the numeric comparison fails.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/a96f334bd756a5a1. Report an issue: GitHub.

Appendix: source

Thrown at skills/council-multi-model/scripts/review-with-codex.js:188

function buildEnvironment(sourceEnv = process.env) {
  const allowed = [
    'PATH', 'HOME', 'USERPROFILE', 'CODEX_HOME',
    'TMPDIR', 'TMP', 'TEMP', 'SystemRoot', 'ComSpec', 'PATHEXT',
  ];
  return Object.fromEntries(
    allowed.filter((name) => sourceEnv[name]).map((name) => [name, sourceEnv[name]])
  );
}

function runReview(prompt, options, dependencies = {}) {
  if (!prompt.trim()) throw new Error('review packet is empty');
  if (Buffer.byteLength(prompt, 'utf8') > MAX_PROMPT_BYTES) {
    throw new Error(`review packet exceeds ${MAX_PROMPT_BYTES} bytes`);
  }
  if (!options.consent) throw new Error('OpenAI transfer consent is required');
  if (options.timeoutMs < 10_000 || options.timeoutMs > MAX_TIMEOUT_MS) {
    throw new Error('timeout is outside the 10-120 second safety range');
  }

  const spawn = dependencies.spawnSync || spawnSync;
  const environment = buildEnvironment(dependencies.env || process.env);
  const verifySupport = dependencies.verifyToollessSupport || verifyToollessSupport;
  verifySupport({ spawnSync: spawn, env: environment });
  const makeTemp = dependencies.mkdtempSync || fs.mkdtempSync;
  const readFile = dependencies.readFileSync || fs.readFileSync;
  const remove = dependencies.rmSync || fs.rmSync;
  const tempDir = makeTemp(path.join(os.tmpdir(), 'ecc-council-review-'));
  const outputFile = path.join(tempDir, 'last-message.txt');

  try {
    const result = spawn('codex', buildCodexArgs(tempDir, outputFile), {
      cwd: tempDir,
      env: environment,
      input: prompt,
      encoding: 'utf8',

View on GitHub (pinned to 8321021c54)