seanmonstar/warp · info
Uri is a valid HeaderValue
Error message
Uri is a valid HeaderValue
What it means
When you pass an `http::Uri` as a redirect location, warp converts it to a `HeaderValue` via `HeaderValue::from_maybe_shared(bytes).expect("Uri is a valid HeaderValue")` (src/redirect.rs:144). The conversion can only fail if the Uri's serialization contains bytes illegal in an HTTP header value (e.g. control characters like \r or \n). Warp panics because a parsed `Uri` should already have excluded such bytes — a header-injection safety invariant.
Solutions
- Build the redirect target with `Uri::from_str` / `http::Uri` validation rather than manual construction
- Sanitize user-supplied redirect targets (reject control characters and CR/LF) before redirecting
- Prefer `warp::redirect(String::parse::<Uri>()?)`-style validated input over raw concatenation
- Guard against open-redirect while you're at it: restrict targets to your own origin
Example fix
// before
let uri: http::Uri = unsafe_target_parse_somehow();
warp::redirect(uri);
// after
let uri: http::Uri = target.parse().map_err(|_| warp::reject::bad_request())?;
if uri.to_string().bytes().any(|b| b < 0x21 || b == 0x7f) { return Err(warp::reject::bad_request()); }
warp::redirect(uri); Defensive patterns
Strategy: validation
Validate before calling
fn safe_redirect_target(s: &str) -> Result<http::Uri, warp::Rejection> {
let uri: http::Uri = s.parse().map_err(|_| warp::reject::bad_request())?;
if uri.to_string().bytes().any(|b| b < 0x21 || b == 0x7f) {
return Err(warp::reject::bad_request());
}
Ok(uri)
} Type guard
fn is_header_safe(s: &str) -> bool {
s.bytes().all(|b| (0x21..=0x7e).contains(&b) || b >= 0x80)
} Prevention
- Construct redirect targets from strictly parsed http::Uri values
- Reject control characters and CR/LF in any user-influenced redirect input
- Also guard against open redirects by whitelisting allowed hosts
When it happens
Trigger: `warp::redirect(uri)` (or `redirect_found`/`see_other`) with a `Uri` that somehow contains forbidden header bytes — practically unreachable via normal `Uri::from_str` parsing, but possible with permissively constructed Uri instances.
Common situations: Not normally hit; relevant if Uri values are built from untrusted string fragments and passed through low-level `http::Uri` constructors that bypass strict validation.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- valid ContentRange
- invalid host/authority
- checked for name previously
- polled after complete
- polled after complete
AI-assisted analysis of seanmonstar/warp@ff34d7213e (2026-09-09).
Data as JSON: /api/errors/b9944b001dbef213.
Report an issue: GitHub.
Appendix: source
Thrown at src/redirect.rs:144
mod sealed {
use bytes::Bytes;
use http::{header::HeaderValue, Uri};
/// Trait for redirect locations. Currently only a `Uri` can be used in
/// redirect.
/// This sealed trait exists to allow adding possibly new impls so other
/// arguments could be accepted, like maybe just `warp::redirect("/v2")`.
pub trait AsLocation: Sealed {}
pub trait Sealed {
fn header_value(self) -> HeaderValue;
}
impl AsLocation for Uri {}
impl Sealed for Uri {
fn header_value(self) -> HeaderValue {
let bytes = Bytes::from(self.to_string());
HeaderValue::from_maybe_shared(bytes).expect("Uri is a valid HeaderValue")
}
}
}
View on GitHub (pinned to ff34d7213e)