openai/codex · critical · CodexErr
Fatal error: {0}
Error message
Fatal error: {0} What it means
CodexErrorDetails::Fatal(String) at error.rs:164-165 prints 'Fatal error: {0}' for conditions the session cannot recover from. It is non-retryable (is_retryable returns false, error.rs:370) and falls through to CodexErrorInfo::Other at the protocol boundary (error.rs:454), so hosts should stop the turn or session and surface the message instead of attempting automatic recovery.
Source
Thrown at codex-rs/protocol/src/error.rs:164
UsageNotIncluded,
#[error("We're currently experiencing high demand, which may cause temporary errors.")]
InternalServerError,
/// Retry limit exceeded.
#[error("{0}")]
RetryLimit(RetryLimitReachedError),
/// Agent loop died unexpectedly
#[error("internal error; agent loop died unexpectedly")]
InternalAgentDied,
/// Sandbox error
#[error("sandbox error: {0}")]
Sandbox(#[from] SandboxErr),
#[error("codex-linux-sandbox was required but not provided")]
LandlockSandboxExecutableNotProvided,
#[error("unsupported operation: {0}")]
UnsupportedOperation(String),
#[error("{0}")]
RefreshTokenFailed(RefreshTokenFailedError),
#[error("Fatal error: {0}")]
Fatal(String),
// -----------------------------------------------------------------
// Automatic conversions for common external error types
// -----------------------------------------------------------------
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
Json(#[from] serde_json::Error),
#[cfg(target_os = "linux")]
#[error(transparent)]
LandlockRuleset(#[from] landlock::RulesetError),
#[cfg(target_os = "linux")]
#[error(transparent)]
LandlockPathFd(#[from] landlock::PathFdError),
#[error(transparent)]
TokioJoin(#[from] JoinError),
#[error("{0}")]
EnvVar(EnvVarError),View on GitHub (pinned to 339751715c)
Solutions
- Stop the current thread or session - do not retry; the variant is non-retryable by classification.
- Read the {0} payload; it names the underlying unrecoverable condition.
- Check environment basics: disk space and permissions on CODEX_HOME and session storage.
- Start a fresh thread; if resuming a rollout triggered it, inspect or discard that rollout file.
- If reproducible, capture the payload and report via /feedback - Fatal often marks an internal defect.
Example fix
// before: logging and continuing
if let Err(e) = session.run().await {
log::error!("{e}"); // keeps a corrupted session alive
}
// after: treat Fatal as terminal
match err.details() {
CodexErrorDetails::Fatal(msg) => {
session.shutdown().await?;
report_and_exit(msg);
}
_ => return Err(err.into()),
} Defensive patterns
Strategy: try-catch
Type guard
fn is_fatal(err: &CodexErr) -> bool {
matches!(err.details(), CodexErrorDetails::Fatal(_))
} Try / catch
Err(err) if matches!(err.details(), CodexErrorDetails::Fatal(_)) => {
// halt the agent loop, persist nothing further, surface the message
halt_and_report(&err).await;
} Prevention
- Keep sessions and rollouts on storage with free space and write permission.
- Avoid killing the process mid-turn to prevent truncated rollout files.
- Treat Fatal in logs as a signal to file a bug, not to retry.
When it happens
Trigger: Constructed via CodexErr::Fatal(message) (error.rs:335) on unrecoverable internal conditions where no dedicated variant exists - for example session or rollout state that can no longer be persisted or trusted. By design it marks state you must not keep operating on.
Common situations: Disk-full or permission failures while writing rollout/session state escalated to fatal; resuming a truncated or corrupted rollout file; internal defects that lack a specific error variant.
Related errors
- pid-managed app-server shutdown is unsupported on this platf
- pid-managed updater shutdown is unsupported on this platform
- failed to read start time for pid-managed app server {pid}
- pid-managed app server {pid} has no recorded start time
- app-server closed the control socket
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/9924aa6814724dc9.
Report an issue: GitHub.