# What Happens When a Codex Turn Times Out in openai/codex-plugin-cc

> Discover what happens when a Codex turn times out in openai/codex-plugin-cc. Learn how timeouts are detected, requests aborted, and partial output returned.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: internals
- Published: 2026-07-14

---

**When a Codex turn exceeds its execution window, the `process` module detects the timeout via `Promise.race`, aborts the underlying request, updates the shared state to `timed_out`, triggers any configured rescue agent, and returns a status object containing partial output to the caller.**

In the `openai/codex-plugin-cc` repository, a **turn** represents a single interaction between a user and the Codex engine. Understanding how the system handles timeouts is critical for building resilient AI-powered workflows. This article examines the timeout lifecycle implementation across the core process and state modules.

## The Turn Timeout Lifecycle

When a Codex turn exceeds its allotted execution window, the system executes a five-phase recovery sequence designed to release resources and preserve diagnostic context.

### 1. Timeout Detection via Promise.race

The `process` module (`plugins/codex/scripts/lib/process.mjs`) wraps each Codex request in a `Promise.race` against a `setTimeout` timer. If the timer fires before the request completes, the turn is flagged for termination.

### 2. Graceful Cancellation and Abort

Upon detection, the plugin invokes the **abort controller** exposed by the Codex library (`plugins/codex/scripts/lib/codex.mjs`) to cancel the in-flight request. This ensures that underlying network connections and compute resources are released promptly rather than hanging indefinitely.

### 3. State Persistence in the State Module

The shared `state` module (`plugins/codex/scripts/lib/state.mjs`) records the timeout event, updating the turn's status to `timed_out` and preserving any metadata required for subsequent hooks. This centralized state ensures that all components observe a consistent view of the turn's lifecycle.

### 4. Rescue Agent Activation

If a **rescue command** is defined (see [`plugins/codex/agents/codex-rescue.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/agents/codex-rescue.md)), the system automatically triggers this agent to perform cleanup operations, emit diagnostic information, and optionally retry the turn. The rescue agent operates as a safety net for automated recovery.

### 5. Client Response with Partial Output

The final response sent to the caller includes a `status: "timeout"` field and any **partial output** accumulated before the abort occurred. This allows client applications to handle degraded responses gracefully while maintaining visibility into execution progress.

## Key Source Files and Responsibilities

The timeout handling logic is distributed across several specialized modules:

- **`plugins/codex/scripts/lib/process.mjs`**: Core orchestration of Codex turns; implements the `Promise.race` timeout guard and `runTurn` function.
- **`plugins/codex/scripts/lib/state.mjs`**: Central state store providing `getState` and persistence for turn status, including `timed_out` states.
- **`plugins/codex/scripts/lib/codex.mjs`**: Wrapper around the Codex API providing abortable request objects and the underlying abort controller.
- **[`plugins/codex/agents/codex-rescue.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/agents/codex-rescue.md)**: Definition and configuration of the rescue agent triggered automatically on timeout.
- **`plugins/codex/scripts/lib/session-lifecycle-hook.mjs`**: Hooks that tie turn lifecycle events (start, finish, timeout) to broader session management.

## Handling Timeouts in Your Code

The following examples demonstrate how to interact with the timeout lifecycle programmatically.

### Running a Turn with Explicit Timeout Handling

Use the `runTurn` function from the process module to execute a Codex interaction with custom timeout logic:

```javascript
import { runTurn } from './plugins/codex/scripts/lib/process.mjs';

const TURN_TIMEOUT_MS = 30_000; // 30 seconds

try {
  const result = await runTurn({
    prompt: 'Explain the bubble sort algorithm.',
    timeoutMs: TURN_TIMEOUT_MS,
  });
  console.log('Turn completed:', result);
} catch (err) {
  if (err.name === 'TimeoutError') {
    console.error('The turn timed out after', TURN_TIMEOUT_MS, 'ms');
    // Optional: invoke rescue logic manually
    // await invokeRescueAgent();
  } else {
    console.error('Turn failed:', err);
  }
}

```

### Inspecting Turn State After Timeout

After a timeout occurs, inspect the shared state to retrieve diagnostic information and partial outputs:

```javascript
import { getState } from './plugins/codex/scripts/lib/state.mjs';

const state = await getState(turnId);
if (state.status === 'timed_out') {
  console.log('Turn timed out. Reason:', state.reason);
  // Access any partial output generated before abort
  console.log('Partial output:', state.partialOutput);
}

```

## Summary

- **Timeout Detection**: The `process` module uses `Promise.race` with a `setTimeout` to detect when a turn exceeds its execution window.
- **Graceful Abort**: The system cancels the underlying Codex request via an abort controller to release resources immediately.
- **State Management**: The `state` module updates the turn status to `timed_out` and preserves metadata for debugging.
- **Rescue Activation**: Configured rescue agents in [`codex-rescue.md`](https://github.com/openai/codex-plugin-cc/blob/main/codex-rescue.md) automatically execute cleanup and diagnostic routines.
- **Client Visibility**: Timeouts return a `status: "timeout"` response including any partial output accumulated before cancellation.

## Frequently Asked Questions

### How is the timeout duration configured for a Codex turn?

The timeout duration is passed as the `timeoutMs` parameter to the `runTurn` function in `plugins/codex/scripts/lib/process.mjs`. If the Codex request does not complete within this millisecond window, the `Promise.race` resolves with the timeout trigger, initiating the abort sequence.

### What happens to partial output when a turn times out?

Partial output generated before the abort signal is captured and preserved in the shared state managed by `plugins/codex/scripts/lib/state.mjs`. The `getState` function returns a state object containing a `partialOutput` field, which is included in the final client response to provide visibility into execution progress.

### Can the rescue agent behavior be customized per turn?

Yes. The rescue agent is defined in [`plugins/codex/agents/codex-rescue.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/agents/codex-rescue.md) and can be configured to execute specific cleanup logic, emit diagnostic information, or retry the turn. While the system triggers rescue automatically on timeout, you can also invoke rescue logic manually by catching the `TimeoutError` and calling the rescue functions directly.

### How does the timeout mechanism interact with the session lifecycle?

The `session-lifecycle-hook.mjs` module subscribes to turn events including timeouts through the state management system. When a turn status changes to `timed_out`, these hooks execute to update session-level tracking, ensuring that resource accounting and logging reflect the terminated turn correctly.