{"record":{"id":"086f39e6db49312f","repo":"openclaw/openclaw","slug":"codex-plugin-thread-config-deadline-elapsed","errorCode":null,"errorMessage":"Codex plugin thread config deadline elapsed","messagePattern":"Codex plugin thread config deadline elapsed","errorType":"exception","errorClass":"CodexPluginThreadConfigDeadlineError","httpStatus":null,"severity":"warning","filePath":"extensions/codex/src/app-server/plugin-thread-config-deadline.ts","lineNumber":114,"sourceCode":"          .toSorted()\n      : undefined,\n  };\n}\n\n/** Builds plugin config without allowing sequential RPC timeouts to consume the turn. */\nasync function buildCodexPluginThreadConfigWithinDeadline(\n  params: BuildCodexPluginThreadConfigWithinDeadlineParams,\n): Promise<CodexPluginThreadConfig> {\n  const { requestTimeoutMs, signal, request, failClosedOnTimeout, transform, ...buildParams } =\n    params;\n  const timeoutMs = resolveCodexPluginThreadConfigTimeoutMs(requestTimeoutMs);\n  // One deadline owns the whole config build; every RPC gets only the remaining\n  // budget so discovery cannot consume one full request timeout per call.\n  const deadlineMs = Date.now() + timeoutMs;\n  const boundedRequest: CodexPluginRuntimeRequest = (method, requestParams) => {\n    const remainingTimeoutMs = deadlineMs - Date.now();\n    if (remainingTimeoutMs <= 0) {\n      throw new CodexPluginThreadConfigDeadlineError();\n    }\n    return request(method, requestParams, {\n      timeoutMs: remainingTimeoutMs,\n      signal,\n    });\n  };\n  try {\n    return await withAbortableTimeout({\n      signal,\n      timeoutMs,\n      promise: (async () => {\n        const config = await buildCodexPluginThreadConfig({\n          ...buildParams,\n          request: boundedRequest,\n        });\n        return transform ? await transform(config, boundedRequest) : config;\n      })(),\n      timeoutMessage: \"Codex plugin thread config deadline elapsed\",","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/codex/src/app-server/plugin-thread-config-deadline.ts#L96-L132","documentation":"Thrown as CodexPluginThreadConfigDeadlineError when the total budget for building Codex plugin thread config has been exhausted. The deadline is computed as requestTimeoutMs/4 clamped to [100ms, 60000ms]. If a subsequent RPC within the config build discovers that the remaining time budget has dropped to zero or below, this error short-circuits before making the request. It is caught internally and either re-thrown as AgentHarnessPreflightError (fail-closed mode) or triggers a timeout fallback that disables plugin apps for the turn.","triggerScenarios":"During buildCodexPluginThreadConfig, the boundedRequest wrapper checks deadlineMs - Date.now() and if it's <= 0, throws immediately without making the RPC. This happens when previous RPCs (config/read, app/installed, etc.) consumed most of the time budget, leaving no time for the next call. Also thrown by the outer withAbortableTimeout wrapper when the overall deadline elapses.","commonSituations":"The Codex app-server is slow or overloaded, causing individual RPCs to eat most of the budget. A large number of plugin apps requiring multiple config reads and app inventory checks within a tight deadline. A requestTimeoutMs configured too low for the number of plugins. Network latency in remote setups consuming time on each RPC.","solutions":["Increase the Codex request timeout in the plugin config so the derived deadline (timeout/4) is large enough for all discovery RPCs.","Reduce the number of enabled Codex plugins to lower the number of RPCs needed during config discovery.","Check the Codex app-server health and latency — a slow app-server is the most common root cause.","For remote setups, reduce network latency or use a local app-server.","If this is a scheduled automation (fail-closed mode), reauthorize after the app-server is responsive again."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isCodexPluginThreadConfigTimeoutError(error: unknown): boolean {\n  return (\n    error instanceof Error &&\n    (error.name === 'CodexPluginThreadConfigDeadlineError' ||\n      ('code' in error &&\n        (error as { code?: string }).code === 'CODEX_APP_SERVER_LOCAL_REQUEST_CANCELLED' &&\n        error.message.endsWith(' timed out')))\n  );\n}","tryCatchPattern":"// The deadline error is caught internally by buildCodexPluginThreadConfigWithinDeadline.\n// For callers of the build function, it either re-throws (fail-closed) or returns a fallback config.\n// To handle externally:\ntry {\n  const config = await startupProvider.build({ threadId });\n} catch (error) {\n  if (error instanceof AgentHarnessPreflightError) {\n    // scheduled automation failed closed; retry later\n  }\n}","preventionTips":["Increase the Codex request timeout so the derived deadline (timeout/4) is sufficient.","Reduce the number of enabled plugins to lower RPC count during discovery.","Keep the Codex app-server responsive and warm.","Monitor app-server latency and address slow RPCs proactively."],"tags":["codex","timeout","deadline","config","app-server"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}