openai/codex · error · RouteAwareRequestError

redirect target uses unsupported URL scheme: {0}

Error message

redirect target uses unsupported URL scheme: {0}

What it means

RouteAwareRequestError::UnsupportedRedirectScheme is raised during the pool's manual redirect following (route_aware_client_pool.rs:635-639). Under RespectSystemProxy (or TLS-backend fallback) reqwest's internal redirects are disabled so each hop gets its own route decision; when a 301/302/303/307/308 Location resolves to a URL whose scheme is not http or https, the pool refuses to follow and returns this error with the offending scheme as its string.

Source

Thrown at codex-rs/http-client/src/route_aware_client_pool.rs:96

/// Error returned when selecting a route or constructing its pooled HTTP client.
#[derive(Debug, thiserror::Error)]
pub enum RouteAwareClientPoolError {
    #[error("failed to resolve the outbound proxy route: {0}")]
    Resolve(#[source] io::Error),
    #[error(transparent)]
    Build(#[from] BuildRouteAwareHttpClientError),
}

/// Error returned while building, routing, or sending a route-aware request.
#[derive(Debug, thiserror::Error)]
pub enum RouteAwareRequestError {
    #[error(transparent)]
    Request(#[from] reqwest::Error),
    #[error(transparent)]
    Route(#[from] RouteAwareClientPoolError),
    #[error("failed to build route-aware request: {0}")]
    Build(String),
    #[error("redirect target uses unsupported URL scheme: {0}")]
    UnsupportedRedirectScheme(String),
    #[error("too many redirects")]
    TooManyRedirects,
    #[error("route-aware request timed out")]
    Timeout,
}

impl RouteAwareRequestError {
    /// Classifies transport, proxy, and certificate failures without exposing request details.
    pub fn failure_class(&self) -> Option<RouteFailureClass> {
        if self.is_timeout() {
            return Some(RouteFailureClass::ConnectTimeout);
        }
        if self.status() == Some(StatusCode::PROXY_AUTHENTICATION_REQUIRED) {
            return Some(RouteFailureClass::ProxyAuthenticationRequired);
        }
        if let Self::Route(RouteAwareClientPoolError::Resolve(error)) = self
            && let Some(source) = error.get_ref()

View on GitHub (pinned to 339751715c)

Solutions

  1. Trace the redirect chain (curl -IL) and fix the server's Location target to an http/https URL
  2. If the target scheme is legitimately outside HTTP, handle it at the application layer instead of expecting the pool to follow it
  3. Use a pool built with RouteAwareClientPool::new_without_redirects so each 3xx response is returned to your code and you decide which hops to follow
  4. Do not retry: the same Location will fail identically

Example fix

// before
let pool = RouteAwareClientPool::new(factory, ClientRouteClass::Api);
let resp = pool.get(url).send().await?; // UnsupportedRedirectScheme("ftp")

// after: observe redirects yourself and follow only http/https
let pool = RouteAwareClientPool::new_without_redirects(factory, ClientRouteClass::Api);
let resp = pool.get(url).send().await?;
if resp.status().is_redirection() { /* read Location, decide, re-send */ }
Defensive patterns

Strategy: try-catch

Type guard

fn is_unsupported_redirect(e: &RouteAwareRequestError) -> bool {
    matches!(e, RouteAwareRequestError::UnsupportedRedirectScheme(_))
}

Try / catch

Err(RouteAwareRequestError::UnsupportedRedirectScheme(scheme)) => {
    // surface the original destination; do not follow non-HTTP schemes
    Err(Upstream::RedirectScheme { scheme, from: original_url })
}

Prevention

When it happens

Trigger: Sending through a RouteAwareClientPool that follows redirects manually when the server answers 3xx with Location: ftp://..., file://..., or any non-http(s) URI: the scheme check at route_aware_client_pool.rs:635 fails and the send aborts instead of following the hop.

Common situations: Legacy download endpoints still redirecting to ftp://, misconfigured server or CDN redirect rules, open-redirect probes pointing at exotic schemes, local dev servers redirecting to internal tooling URLs.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/e9c0991e61707c4b. Report an issue: GitHub.