seanmonstar/reqwest · error · reqwest::Error

URL scheme is not allowed

Error message

URL scheme is not allowed

What it means

The `BadScheme` source wrapped in `Kind::Builder` via `error::url_bad_scheme` (error.rs:387-389). It means the URL's scheme is not acceptable: anything other than `http`/`https` for a normal client, or anything other than `https` when the client is https-only. Constructed in `IntoUrl` (into_url.rs:37), at request dispatch (client.rs:2623/2628), and during redirects (redirect.rs:321/326).

Source

Thrown at src/error.rs:388

    status: StatusCode,
    #[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))] reason: Option<hyper::ext::ReasonPhrase>,
) -> Error {
    Error::new(
        Kind::Status(
            status,
            #[cfg(not(all(
                target_arch = "wasm32",
                any(target_os = "unknown", target_os = "none")
            )))]
            reason,
        ),
        None::<Error>,
    )
    .with_url(url)
}

pub(crate) fn url_bad_scheme(url: Url) -> Error {
    Error::new(Kind::Builder, Some(BadScheme)).with_url(url)
}

pub(crate) fn url_invalid_uri(url: Url) -> Error {
    Error::new(Kind::Builder, Some("Parsed Url is not a valid Uri")).with_url(url)
}

if_wasm! {
    pub(crate) fn wasm(js_val: wasm_bindgen::JsValue) -> BoxError {
        format!("{js_val:?}").into()
    }
}

pub(crate) fn upgrade<E: Into<BoxError>>(e: E) -> Error {
    Error::new(Kind::Upgrade, Some(e))
}

// io::Error helpers

View on GitHub (pinned to 17e9bcb51c)

Solutions

  1. Prefix the URL with `https://` (or `http://` if plaintext is acceptable).
  2. Don't enable `.https_only(true)` if you must reach plaintext hosts.
  3. Validate `url.scheme() == "http" || url.scheme() == "https"` before calling `.send()`.
  4. For redirects, ensure servers return http(s) `Location` headers.

Example fix

// before
let r = client.get("file:///etc/hosts").send().await?; // 'URL scheme is not allowed'

// after
let raw = "example.com/api";
let url = if raw.starts_with("http://") || raw.starts_with("https://") {
    raw.to_string()
} else {
    format!("https://{raw}")
};
let r = client.get(url).send().await?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_http_scheme(raw: &str) -> anyhow::Result<String> {
    let u = url::Url::parse(raw).map_err(|e| anyhow!("bad url: {e}"))?;
    match u.scheme() {
        "http" | "https" => Ok(raw.to_string()),
        _ => Err(anyhow!("scheme '{}' not allowed", u.scheme())),
    }
}

Type guard

fn is_bad_scheme(e: &reqwest::Error) -> bool {
    e.is_builder() && e.source().map(|s| s.to_string() == "URL scheme is not allowed").unwrap_or(false)
}

Try / catch

let url = ensure_http_scheme(&raw)?;
let resp = client.get(url).send().await?;

Prevention

When it happens

Trigger: Passing `file:///...`, `ftp://`, `ws://`, `data:`, or a scheme-less string like `example.com`; an https-only client (`.https_only(true)`) being pointed at `http://`; a redirect target with a non-http scheme.

Common situations: Missing `https://` prefix; reading a path that's actually a `file://` URL; localhost dev with `http://` against a production https-only client; redirect to `ftp://` from a misconfigured server.

Related errors


AI-assisted analysis of seanmonstar/reqwest@17e9bcb51c (2026-08-06). Data as JSON: /data/errors/f97a850abae2bbd0.json. Report an issue: GitHub.