{"record":{"id":"a96f334bd756a5a1","repo":"affaan-m/ECC","slug":"timeout-is-outside-the-10-120-second-safety-range","errorCode":null,"errorMessage":"timeout is outside the 10-120 second safety range","messagePattern":"timeout is outside the 10-120 second safety range","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/council-multi-model/scripts/review-with-codex.js","lineNumber":188,"sourceCode":"\nfunction buildEnvironment(sourceEnv = process.env) {\n  const allowed = [\n    'PATH', 'HOME', 'USERPROFILE', 'CODEX_HOME',\n    'TMPDIR', 'TMP', 'TEMP', 'SystemRoot', 'ComSpec', 'PATHEXT',\n  ];\n  return Object.fromEntries(\n    allowed.filter((name) => sourceEnv[name]).map((name) => [name, sourceEnv[name]])\n  );\n}\n\nfunction runReview(prompt, options, dependencies = {}) {\n  if (!prompt.trim()) throw new Error('review packet is empty');\n  if (Buffer.byteLength(prompt, 'utf8') > MAX_PROMPT_BYTES) {\n    throw new Error(`review packet exceeds ${MAX_PROMPT_BYTES} bytes`);\n  }\n  if (!options.consent) throw new Error('OpenAI transfer consent is required');\n  if (options.timeoutMs < 10_000 || options.timeoutMs > MAX_TIMEOUT_MS) {\n    throw new Error('timeout is outside the 10-120 second safety range');\n  }\n\n  const spawn = dependencies.spawnSync || spawnSync;\n  const environment = buildEnvironment(dependencies.env || process.env);\n  const verifySupport = dependencies.verifyToollessSupport || verifyToollessSupport;\n  verifySupport({ spawnSync: spawn, env: environment });\n  const makeTemp = dependencies.mkdtempSync || fs.mkdtempSync;\n  const readFile = dependencies.readFileSync || fs.readFileSync;\n  const remove = dependencies.rmSync || fs.rmSync;\n  const tempDir = makeTemp(path.join(os.tmpdir(), 'ecc-council-review-'));\n  const outputFile = path.join(tempDir, 'last-message.txt');\n\n  try {\n    const result = spawn('codex', buildCodexArgs(tempDir, outputFile), {\n      cwd: tempDir,\n      env: environment,\n      input: prompt,\n      encoding: 'utf8',","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/council-multi-model/scripts/review-with-codex.js#L170-L206","documentation":"runReview clamps the Codex subprocess timeout to the closed interval [10_000, MAX_TIMEOUT_MS] ms, i.e. 10s to 120s. Values outside that range are rejected so the review neither fails from an impossibly short budget nor hangs unbounded. The CLI parseArgs already validates --timeout-seconds as an integer 10-120, but runReview re-checks the millisecond value to protect programmatic callers.","triggerScenarios":"Calling runReview with options.timeoutMs < 10000 or options.timeoutMs > 120000. Common root cause: passing seconds (e.g. 60) instead of milliseconds (60000), or passing 0.","commonSituations":"Treating timeoutMs as seconds; passing timeout: 0 meaning 'no timeout'; unit tests using a tiny timeout to force fast failure; copying a value from a config that used seconds.","solutions":["Set options.timeoutMs to a value between 10000 and 120000 (inclusive).","If your config uses seconds, multiply by 1000 before passing: options.timeoutMs = seconds * 1000.","Leave timeoutMs unset to accept the 60_000 default."],"exampleFix":"// before (seconds passed as ms)\nrunReview(packet, { consent: true, timeoutMs: 60, hostProvider: 'openai' });\n\n// after\nrunReview(packet, { consent: true, timeoutMs: 60_000, hostProvider: 'openai' });","handlingStrategy":"validation","validationCode":"const MIN_TIMEOUT_MS = 10_000;\nconst MAX_TIMEOUT_MS = 120_000;\nfunction clampTimeout(ms) {\n  if (!Number.isFinite(ms) || ms < MIN_TIMEOUT_MS || ms > MAX_TIMEOUT_MS) {\n    throw new Error(`timeoutMs must be within [${MIN_TIMEOUT_MS}, ${MAX_TIMEOUT_MS}]`);\n  }\n  return ms;\n}\noptions.timeoutMs = clampTimeout(options.timeoutMs ?? 60_000);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Name timeouts in milliseconds everywhere (timeoutMs) to avoid the seconds/ms confusion.","Default to the 60_000ms constant when unset instead of passing 0 or undefined.","If accepting user input in seconds, multiply by 1000 at the boundary and validate."],"tags":["validation","timeout","bounds","codex"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}