# What Happens When Codex Returns an Error During Review or Task Execution

> Learn what happens when Codex returns an error in review or task execution. Discover how openai/codex-plugin-cc handles errors, retries failures, and provides details for your handling.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: how-to-guide
- Published: 2026-07-28

---

**When Codex returns an error during a review or task execution, the openai/codex-plugin-cc captures the error in a `TurnCaptureState` object, emits a failed progress notification, and exposes the error details in the result object for caller handling, while automatically retrying broker transport failures via direct connection fallback.**

The `openai/codex-plugin-cc` repository provides a plugin interface for executing Codex reviews and tasks within continuous integration workflows. Understanding the error handling flow is essential for building resilient automation that can respond to network failures, authentication problems, or runtime exceptions gracefully.

## Error Capture and Notification Flow

When the Codex app-server encounters an error, it communicates the failure through a structured JSON-RPC notification that the plugin processes and stores for later inspection.

### JSON-RPC Error Notification Handling

The Codex app-server sends a notification with `method: "error"` containing the error payload. In `plugins/codex/scripts/lib/codex.mjs`, the notification handler routes this to `applyTurnNotification`, which stores the error and updates the progress state:

```javascript
// plugins/codex/scripts/lib/codex.mjs
case "error":
  state.error = message.params.error;
  emitProgress(state.onProgress, `Codex error: ${message.params.error.message}`, "failed");
  break;

```

This code populates `state.error` with the full error object and signals a **failed** phase to any registered progress listeners, providing immediate visibility into the failure.

### Turn State Population

The `captureTurn` function awaits the turn’s completion promise. When an error has been recorded in the state, the promise resolves with the populated `TurnCaptureState`, ensuring the error persists alongside other turn metadata like `threadId` and `turnId`.

## Error Propagation to Callers

High-level helper functions expose errors through standardized result objects, allowing calling code to implement conditional logic based on the failure type.

### Result Object Structure

Both `runAppServerReview` and `runAppServerTurn` return a result object that explicitly includes the captured error:

```javascript
// plugins/codex/scripts/lib/codex.mjs
return {
  status: buildResultStatus(turnState),
  threadId: turnState.threadId,
  turnId: turnState.turnId,
  ...,
  error: turnState.error,
  stderr: cleanCodexStderr(client.stderr)
};

```

Callers can inspect `result.error` to determine whether to retry the operation, surface a user-friendly message, or abort the workflow entirely.

### Error Inspection Patterns

The error object contains standard properties including `message` and `code`, enabling programmatic error classification. For example, network-related errors like `ENETUNREACH` or authentication failures can be distinguished and handled with specific recovery strategies.

## Automatic Retry Mechanism for Transport Failures

The plugin implements transparent resilience for transport-layer failures by detecting broker connection issues and automatically falling back to direct connections.

### Broker to Direct Connection Fallback

If the error originates from the shared broker transport—specifically when encountering `BROKER_BUSY_RPC_CODE`, `ENOENT`, or `ECONNREFUSED`—the `withAppServer` wrapper triggers an automatic retry:

```javascript
// plugins/codex/scripts/lib/codex.mjs
const brokerRequested = client?.transport === "broker" || Boolean(process.env[BROKER_ENDPOINT_ENV]);
const shouldRetryDirect =
  (client?.transport === "broker" && error?.rpcCode === BROKER_BUSY_RPC_CODE) ||
  (brokerRequested && (error?.code === "ENOENT" || error?.code === "ECONNREFUSED"));

```

When `shouldRetryDirect` evaluates to true, the wrapper creates a new direct client and re-executes the original function, providing seamless recovery without manual intervention.

## Code Examples

### Handling Errors in Review Operations

Use `runAppServerReview` to execute a code review and handle potential failures:

```javascript
import { runAppServerReview } from "./plugins/codex/scripts/lib/codex.mjs";

async function doReview(cwd) {
  try {
    const result = await runAppServerReview(cwd, {
      onProgress: console.log,
      target: { type: "branch", ref: "main" }
    });

    if (result.error) {
      console.error("Review failed:", result.error.message);
      // Decide whether to retry, show UI, or abort.
      return;
    }

    console.log("Review text:", result.reviewText);
  } catch (e) {
    // Unexpected exception (e.g., missing Codex binary)
    console.error("Unable to start review:", e.message);
  }
}

```

### Detecting Failures in Task Execution

When running a task with `runAppServerTurn`, check the result error property to detect execution failures:

```javascript
import { runAppServerTurn } from "./plugins/codex/scripts/lib/codex.mjs";

async function runTask(cwd, prompt) {
  const result = await runAppServerTurn(cwd, {
    prompt,
    onProgress: console.log
  });

  if (result.error) {
    // The Codex app-server reported an error during execution.
    console.error("Task error:", result.error.message);
    // Example: retry if the error is a transient network issue.
    if (result.error.code === "ENETUNREACH") {
      // retry logic …
    }
    return;
  }

  console.log("Final answer:", result.finalMessage);
}

```

### Implementing Safe Operations with Automatic Retry

Leverage `withAppServer` to benefit from automatic broker-to-direct fallback:

```javascript
import { withAppServer } from "./plugins/codex/scripts/lib/codex.mjs";

async function safeOperation(cwd, operation) {
  return await withAppServer(cwd, async (client) => {
    // `operation` may throw an error that triggers automatic retry.
    return await operation(client);
  });
}

```

## Summary

- **Error Capture**: The plugin stores Codex errors in `TurnCaptureState.error` when receiving JSON-RPC error notifications from the app-server.
- **Progress Reporting**: Failed operations emit progress updates with a "failed" phase through `emitProgress`, enabling real-time UI updates.
- **Result Exposure**: High-level functions return result objects containing `error`, `stderr`, and turn identifiers, allowing callers to inspect failure details.
- **Transport Resilience**: The `withAppServer` wrapper automatically retries operations using a direct connection when broker transport fails with specific error codes (`ENOENT`, `ECONNREFUSED`, or `BROKER_BUSY_RPC_CODE`).

## Frequently Asked Questions

### How does the plugin distinguish between different types of Codex errors?

The plugin relies on standard error properties such as `error.code` and `error.rpcCode` to classify failures. Transport errors like `ECONNREFUSED` or `ENOENT` trigger automatic retry logic, while application-level errors (such as authentication failures) are captured in `TurnCaptureState` and returned to the caller for manual handling.

### Can I disable the automatic broker retry behavior?

The automatic retry logic is embedded in the `withAppServer` function within `plugins/codex/scripts/lib/codex.mjs`. To disable it, you would need to avoid using `withAppServer` and instead instantiate the `CodexAppServerClient` directly from `plugins/codex/scripts/lib/app-server.mjs`, managing connection failures manually in your calling code.

### What information is included in the error object returned by runAppServerReview?

The error object contains at minimum a `message` property describing the failure, and often includes a `code` property for programmatic identification. For broker-related failures, an `rpcCode` property may also be present. The full error object is passed directly from the Codex app-server's JSON-RPC notification to the result object.

### Where should I check for errors when implementing a custom Codex workflow?

Always inspect the `error` property of the result object returned by `runAppServerReview`, `runAppServerTurn`, or `captureTurn`. Additionally, monitor the `stderr` property for auxiliary error output from the Codex client process, which may contain diagnostic information not present in the structured error object.