seanmonstar/warp · error

invalid header name

Error message

invalid header name

What it means

The reply::WithHeader/WithHeaders extension panics with 'invalid header name' when the header key passed to reply::with_header cannot be converted into an http::HeaderName via assert_name_and_value. Invalid keys (empty strings, non-token characters) are treated as programmer errors.

Solutions

  1. Use a valid header name literal or an http::header:: constant
  2. Validate the dynamic key with HeaderName::try_from before calling with_header
  3. Fix string-building logic that produces empty or malformed names

Example fix

// before
reply::with_header(&format!("{}-{}", prefix, suffix), "v")
// after
let name = format!("{}-{}", prefix, suffix);
assert!(HeaderName::try_from(name.as_str()).is_ok(), "invalid header name");
reply::with_header(name, "v")
Defensive patterns

Strategy: validation

Validate before calling

if HeaderName::try_from(name.as_str()).is_err() { panic!("bad reply header name: {}", name); }

Type guard

fn valid_reply_header_name(k: &str) -> Option<HeaderName> { HeaderName::try_from(k).ok() }

Prevention

When it happens

Trigger: reply::with_header("", "value"), reply::with_header("bad header", "v"), or any dynamic key failing HeaderName conversion when attaching headers to a reply.

Common situations: Injecting headers from request-derived or config-derived strings; typos like 'Content- Type'; constructing names by concatenation producing empty/invalid results.

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/bfbf284e36107755. Report an issue: GitHub.

Appendix: source

Thrown at src/filters/reply.rs:189

{
    type Wrapped = Map<F, WithDefaultHeader_>;

    fn wrap(&self, filter: F) -> Self::Wrapped {
        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,
    }

View on GitHub (pinned to ff34d7213e)