seanmonstar/warp · error
invalid header value
Error message
invalid header value
What it means
assert_name_and_value in reply.rs panics with 'invalid header value' when the value passed to reply::with_header/default_header cannot be converted into an http::HeaderValue. HeaderValues must be visible ASCII (or obs-text); bytes with control characters, newlines, or invalid UTF-8 fail conversion.
Solutions
- Sanitize the value: strip \r, \n and non-visible-ASCII bytes before use
- Use HeaderValue::from_bytes/mime-percent-encode and only pass if conversion succeeds
- Move large/binary data into the response body instead of headers
Example fix
// before
reply::with_header("x-note", &user_input)
// after
let v = user_input.chars().filter(|c| !c.is_control()).collect::<String>();
reply::with_header("x-note", v) Defensive patterns
Strategy: validation
Validate before calling
fn valid_header_value(v: &str) -> bool { HeaderValue::try_from(v).is_ok() }
assert!(valid_header_value(value)); Type guard
fn sanitized_header_value(v: &str) -> Option<HeaderValue> { HeaderValue::try_from(v.chars().filter(|c| !c.is_control()).collect::<String>()).ok() } Prevention
- Strip control characters (\r, \n, NUL) from values destined for headers
- Never echo raw user/binary input into headers
- Use HeaderValue::from_bytes as a pre-check
When it happens
Trigger: reply::with_header("x-id", "line1\nline2"), passing raw binary/UTF-8 multibyte data, or values containing NUL bytes.
Common situations: Echoing user input or file contents into response headers; header-injection sanitization failures; logging payloads into headers.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of seanmonstar/warp@ff34d7213e (2026-09-09).
Data as JSON: /api/errors/321e7763e9bd9fb6.
Report an issue: GitHub.
Appendix: source
Thrown at src/filters/reply.rs:193
let with = WithDefaultHeader_ { with: self.clone() };
filter.map(with)
}
}
fn assert_name_and_value<K, V>(name: K, value: V) -> (HeaderName, HeaderValue)
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let name = <HeaderName as TryFrom<K>>::try_from(name)
.map_err(Into::into)
.unwrap_or_else(|_| panic!("invalid header name"));
let value = <HeaderValue as TryFrom<V>>::try_from(value)
.map_err(Into::into)
.unwrap_or_else(|_| panic!("invalid header value"));
(name, value)
}
mod sealed {
use super::{WithDefaultHeader, WithHeader, WithHeaders};
use crate::generic::{Func, One};
use crate::reply::{Reply, Reply_};
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct WithHeader_ {
pub(super) with: WithHeader,
}
impl<R: Reply> Func<One<R>> for WithHeader_ {
type Output = Reply_;
View on GitHub (pinned to ff34d7213e)