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

  1. Sanitize the value: strip \r, \n and non-visible-ASCII bytes before use
  2. Use HeaderValue::from_bytes/mime-percent-encode and only pass if conversion succeeds
  3. 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

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)