seanmonstar/reqwest · error · reqwest::Error

Parsed Url is not a valid Uri

Error message

Parsed Url is not a valid Uri

What it means

Constructed by `error::url_invalid_uri` (error.rs:391-393) as `Kind::Builder`. It fires when a URL parses fine as a `url::Url` but then fails to re-parse as an `http::Uri` in `try_uri` (into_url.rs:77-81, client.rs:2639-2641). The `Url` and `Uri` grammars differ, so a valid URL can still be unusable as an HTTP target.

Source

Thrown at src/error.rs:392

        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

#[allow(unused)]
pub(crate) fn decode_io(e: io::Error) -> Error {
    if e.get_ref().map(|r| r.is::<Error>()).unwrap_or(false) {
        *e.into_inner()

View on GitHub (pinned to 17e9bcb51c)

Solutions

  1. Inspect the exact URL string from `e.url()` and re-encode/normalize it (e.g. via `url::Url` normalization or punycode the host).
  2. Simplify the URL — drop unusual userinfo, percent-encode path/query properly — and retry.
  3. If reproducible, file the failing input against `http`/`hyper` with the rejected substring.

Example fix

// before
let r = client.get(raw_url).send().await?; // 'Parsed Url is not a valid Uri'

// after
let parsed = url::Url::parse(&raw_url)?;
// re-encode host to ASCII / normalize, then send the canonical form
let canon = parsed.to_string();
let r = client.get(canon).send().await?;
Defensive patterns

Strategy: validation

Validate before calling

fn normalize_for_http(raw: &str) -> anyhow::Result<String> {
    let u = url::Url::parse(raw)?;
    let s = u.to_string();
    s.parse::<http::Uri>().map_err(|e| anyhow!("not a valid Uri: {e}"))?;
    Ok(s)
}

Type guard

fn is_invalid_uri(e: &reqwest::Error) -> bool {
    e.is_builder() && e.source().map(|s| s.to_string() == "Parsed Url is not a valid Uri").unwrap_or(false)
}

Try / catch

let url = normalize_for_http(&raw).unwrap_or_else(|_| {
    log::warn!("url rejected by http::Uri, falling back to base");
    base_url.clone()
});
let resp = client.get(url).send().await?;

Prevention

When it happens

Trigger: URLs containing characters or structures legal to `url` but rejected by `http::Uri` — e.g. certain encoded characters in the authority, non-ASCII host without proper handling, or overly long components exceeding `Uri` limits.

Common situations: Internationalized domain names handled differently between `url` and `http`; exotic percent-encoding in userinfo; copied URL with unusual characters that `Url::parse` accepts but `hyper`/`http` rejects.

Related errors


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