openai/codex · error · TransportError
connection failed
Error message
connection failed: {0} What it means
TransportError::Connection wraps a reqwest error for which is_connect() is true; the reqwest error is preserved as #[source] and the request URL is stripped via without_url() (transport.rs:82). It means the transport never completed an HTTP exchange: DNS resolution, TCP connect, or the TLS handshake to the origin or proxy failed. Inspect .source() for the underlying reqwest error details.
Solutions
- Inspect the preserved source error (error.source() downcast to reqwest::Error) to distinguish DNS vs refused vs TLS failure
- Verify host, port, and reachability of the endpoint directly (dig/curl) and through the proxy if one is required
- For TLS causes, install the enterprise root CA via the custom-CA transport path (build_reqwest_client_with_custom_ca) instead of disabling verification
- Retry with backoff: connection failures are often transient (restarts, port exhaustion)
Example fix
// before
match transport.execute(req).await {
Err(e) => log::error!("request failed: {e}"), // opaque
r => r?,
}
// after: classify using the preserved reqwest source
if let TransportError::Connection(source) = &error {
if source.is_connect() && source.to_string().contains("dns error") { /* host/port config */ }
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight DNS check before first use (cheap, caches at the resolver)
async fn endpoint_reachable(host: &str, port: u16) -> bool {
tokio::net::lookup_host((host, port)).await.is_ok()
} Type guard
fn is_connection_failure(e: &TransportError) -> bool {
matches!(e, TransportError::Connection(_))
} Try / catch
if let TransportError::Connection(source) = &error {
let detail = source.to_string();
if detail.contains("dns error") { return ConfigError::BadHost(detail); }
if detail.contains("tls") || detail.contains("certificate") { return ConfigError::Tls(detail); }
}
// otherwise: transient connect failure, retry idempotent requests with backoff Prevention
- Validate configured hosts and ports at startup with a resolve probe
- Install enterprise CAs through the custom-CA transport instead of skipping verification
- Keep a bounded retry with exponential backoff for connect-phase failures
- Run synthetic health checks against critical endpoints
When it happens
Trigger: HttpTransport::execute/stream fails during send with a reqwest is_connect() error: DNS lookup failure (unknown host), connection refused (server down or wrong port), TLS handshake or certificate failure while connecting, or an unreachable configured proxy.
Common situations: Wrong hostname or port in configuration, DNS/hosts-file breakage, firewall blocking egress, corporate proxy required but not configured, self-signed or enterprise CA not installed via the custom-CA path, server temporarily down for deployment.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- empty proxy connection
- Luna Responses WebSocket connection timed out
- network error
- route-aware request timed out
- stream failed
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/6e0320f3b4b772c3.
Report an issue: GitHub.
Appendix: source
Thrown at codex-rs/http-client/src/error.s:21
//! Errors returned by the shared Codex HTTP transport.
use crate::client::HttpError;
use http::HeaderMap;
use http::StatusCode;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum TransportError {
#[error("http {status}: {body:?}")]
Http {
status: StatusCode,
url: Option<String>,
headers: Option<HeaderMap>,
body: Option<String>,
},
#[error("retry limit reached")]
RetryLimit,
#[error("timeout")]
Timeout,
#[error("connection failed: {0}")]
Connection(#[source] HttpError),
#[error("network error: {0}")]
Network(String),
#[error("request build error: {0}")]
Build(String),
}View on GitHub (pinned to 339751715c)