{"record":{"id":"953460b6f3618e3a","repo":"openai/codex","slug":"failed-to-resolve-the-outbound-proxy-route-0","errorCode":null,"errorMessage":"failed to resolve the outbound proxy route: {0}","messagePattern":"failed to resolve the outbound proxy route: (.+?)","errorType":"exception","errorClass":"RouteAwareClientPoolError","httpStatus":null,"severity":"error","filePath":"codex-rs/http-client/src/route_aware_client_pool.rs","lineNumber":81,"sourceCode":"    custom_ca_fallback: CustomCaFallback,\n    clients: Arc<Mutex<HashMap<OutboundProxyRoute, HttpClient>>>,\n    rustls_clients: Option<RustlsClientCache>,\n}\n\nimpl fmt::Debug for RouteAwareClientPool {\n    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        formatter\n            .debug_struct(\"RouteAwareClientPool\")\n            .field(\"http_client_factory\", &self.http_client_factory)\n            .field(\"route_class\", &self.route_class)\n            .finish_non_exhaustive()\n    }\n}\n\n/// Error returned when selecting a route or constructing its pooled HTTP client.\n#[derive(Debug, thiserror::Error)]\npub enum RouteAwareClientPoolError {\n    #[error(\"failed to resolve the outbound proxy route: {0}\")]\n    Resolve(#[source] io::Error),\n    #[error(transparent)]\n    Build(#[from] BuildRouteAwareHttpClientError),\n}\n\n/// Error returned while building, routing, or sending a route-aware request.\n#[derive(Debug, thiserror::Error)]\npub enum RouteAwareRequestError {\n    #[error(transparent)]\n    Request(#[from] reqwest::Error),\n    #[error(transparent)]\n    Route(#[from] RouteAwareClientPoolError),\n    #[error(\"failed to build route-aware request: {0}\")]\n    Build(String),\n    #[error(\"redirect target uses unsupported URL scheme: {0}\")]\n    UnsupportedRedirectScheme(String),\n    #[error(\"too many redirects\")]\n    TooManyRedirects,","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/http-client/src/route_aware_client_pool.rs#L63-L99","documentation":"RouteAwareClientPoolError::Resolve is produced in client_for_url_with_resolver (route_aware_client_pool.rs:723-725) when the async route resolver returns an io::Error. The resolver is HttpClientFactory::resolve_proxy_route_async (outbound_proxy.rs:242-276): on Windows/macOS the platform lookup runs under spawn_blocking, so the io::Error typically comes from the semaphore acquire or the blocking task failing to join (runtime shutdown, task panic); the synchronous resolution itself falls back to env/direct instead of erroring. failure_class() maps it to ProxyResolutionUnavailable (or TlsError when the io::Error carries a rustls error).","triggerScenarios":"Sending via RouteAwareClientPool with RespectSystemProxy on Windows/macOS while the spawn_blocking PAC/WinHTTP/system-proxy lookup fails to join: the tokio runtime is shutting down, the request future is cancelled mid-lookup, or the platform binding panics. It propagates to callers as RouteAwareRequestError::Route(RouteAwareClientPoolError::Resolve(..)).","commonSituations":"Dropping request futures during graceful-shutdown drains in servers, test harnesses tearing down the runtime while sends are in flight, bugs in platform proxy bindings after an upgrade.","solutions":["Check whether the runtime is being shut down or the send future was cancelled while platform proxy resolution was in flight; drain in-flight requests before shutdown","Retry the send: successful resolutions are cached (60s TTL) so a retry usually hits the cache or completes the lookup","Update codex-rs if the platform binding panic is a known issue, and capture the io::Error's source for the report","As a workaround, run with OutboundProxyPolicy::ReqwestDefault or env-only proxies to skip platform resolution entirely"],"exampleFix":"// before\nlet resp = pool.get(url).send().await?; // Resolve(io::Error) aborts the caller\n\n// after: retry once, then fall back to a direct-route factory\nlet resp = match pool.get(url.clone()).send().await {\n    Err(RouteAwareRequestError::Route(RouteAwareClientPoolError::Resolve(_))) =>\n        pool.get(url).send().await?,\n    other => other?,\n};","handlingStrategy":"fallback","validationCode":null,"typeGuard":"fn is_route_resolve_error(e: &RouteAwareRequestError) -> bool {\n    matches!(e, RouteAwareRequestError::Route(RouteAwareClientPoolError::Resolve(_)))\n}","tryCatchPattern":"match error {\n    RouteAwareRequestError::Route(RouteAwareClientPoolError::Resolve(io)) => {\n        tracing::warn!(source = %io, \"proxy route resolution unavailable\");\n        // resolution results are cached; one retry is cheap, then degrade\n        retry_once_or_direct(factory).await\n    }\n    _ => return Err(error),\n}","preventionTips":["Do not abort in-flight sends during runtime shutdown; drain them first","Treat failure_class() == ProxyResolutionUnavailable as 'retry once, then degrade' rather than fatal","Monitor resolver failures separately from TLS and timeout classes","In tests, keep the runtime alive until spawned sends resolve to avoid join failures"],"tags":["proxy","async","tokio","rust"],"backgroundTag":"proxy-resolution-failed","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}