{"record":{"id":"c7a2d2a3ddae8d95","repo":"affaan-m/ECC","slug":"codex-review-timed-out","errorCode":null,"errorMessage":"Codex review timed out","messagePattern":"Codex review timed out","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/council-multi-model/scripts/review-with-codex.js","lineNumber":213,"sourceCode":"  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',\n      timeout: options.timeoutMs,\n      maxBuffer: 1024 * 1024,\n      windowsHide: true,\n    });\n\n    if (result.error) {\n      if (result.error.code === 'ETIMEDOUT') throw new Error('Codex review timed out');\n      if (result.error.code === 'ENOENT') throw new Error('Codex CLI is not installed');\n      throw new Error(`Codex invocation failed: ${result.error.message}`);\n    }\n    if (result.status !== 0) {\n      const detail = (result.stderr || '').trim().split('\\n').slice(-1)[0];\n      throw new Error(`Codex review failed${detail ? `: ${detail}` : ''}`);\n    }\n\n    let text;\n    try {\n      text = readFile(outputFile, 'utf8').trim();\n    } catch (error) {\n      throw new Error(`Codex returned no final response: ${error.message}`);\n    }\n    if (!text) throw new Error('Codex returned an empty final response');\n    return `${providerLabel(options.hostProvider)}\\n${text}`;\n  } finally {\n    remove(tempDir, { recursive: true, force: true });","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/council-multi-model/scripts/review-with-codex.js#L195-L231","documentation":"runReview spawns codex with timeout: options.timeoutMs. When Node's spawnSync kills the subprocess for exceeding that timeout, result.error.code is 'ETIMEDOUT', which this branch re-throws as 'Codex review timed out'. The finally block still removes the temp directory. The default budget is 60s, max 120s.","triggerScenarios":"The codex subprocess runs longer than options.timeoutMs and is killed by Node, yielding result.error.code === 'ETIMEDOUT'.","commonSituations":"Slow or rate-limited network to OpenAI; cold start of the Codex CLI; a large prompt near the 64 KiB ceiling; overloaded API during peak hours; DNS/proxy latency.","solutions":["Increase options.timeoutMs toward the 120000 ceiling (via --timeout-seconds 120 on the CLI).","Reduce the prompt size to speed up the round trip.","Retry transiently; if it persists, run `codex` manually with the same packet to see where time is spent.","Check network/proxy connectivity to OpenAI."],"exampleFix":"// before\nrunReview(packet, { consent: true, timeoutMs: 30_000, hostProvider: 'openai' });\n\n// after\nrunReview(packet, { consent: true, timeoutMs: 120_000, hostProvider: 'openai' });","handlingStrategy":"retry","validationCode":"const MAX_TIMEOUT_MS = 120_000;\n// choose the largest safe budget so transient slowness does not trip the timeout\noptions.timeoutMs = Math.min(desiredTimeoutMs ?? 60_000, MAX_TIMEOUT_MS);","typeGuard":null,"tryCatchPattern":"try {\n  return await runReview(packet, options);\n} catch (error) {\n  if (error.message === 'Codex review timed out' && attempt < MAX_RETRIES) {\n    await backoff(attempt);\n    return runReview(packet, { ...options, timeoutMs: Math.min(options.timeoutMs * 1.5, 120_000) });\n  }\n  throw error;\n}","preventionTips":["Use the largest safe timeout (120s) for batch reviews to absorb network jitter.","Keep prompts well under 64 KiB so the round trip is fast.","Monitor codex latency out-of-band so you notice a degrading API before timeouts cascade."],"tags":["timeout","network","codex","subprocess"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}