actix/actix-web · error

Invalid header value

Error message

Invalid header value

What it means

This is a runtime panic from the deprecated `DefaultHeaders::header()` method. When the provided value cannot be converted into a valid `HeaderValue` via `HeaderValue::try_from(value)`, the `.expect("Invalid header value")` at line 94 panics. Header values must not contain certain bytes like raw newlines (`\n`, `\r`) or other control characters.

Solutions

  1. Sanitize or validate header values before passing them: reject or escape control characters
  2. Use `HeaderValue::try_from(value)` and handle the error instead of panicking
  3. Migrate to the `.add((key, value))` API (though it also panics on invalid values; validation is still needed)
  4. Ensure header values are visible ASCII or valid percent-encoded UTF-8 without raw newlines or control chars

Example fix

// before (deprecated, panics on invalid value)
let mw = DefaultHeaders::new().header("X-Test", user_input); // panics if user_input has \n

// after (validated)
let mw = DefaultHeaders::new();
if let Ok(val) = HeaderValue::try_from(user_input.trim()) {
    let mw = mw.add(("X-Test", val));
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate header values before passing to the middleware.
use actix_web::http::header::HeaderValue;

fn is_valid_header_value(value: &str) -> bool {
    HeaderValue::try_from(value).is_ok()
}

// Sanitize user input before using as header value.
fn sanitize_header_value(input: &str) -> String {
    input.chars().filter(|c| !c.is_control()).collect()
}

Type guard

use actix_web::http::header::HeaderValue;

fn is_valid_header_value(value: &str) -> bool {
    HeaderValue::try_from(value).is_ok()
}

Try / catch

// Do not use the deprecated .header() method. Use .add() with validation:
let mw = DefaultHeaders::new();
if let Ok(val) = HeaderValue::try_from(sanitized_value) {
    let mw = mw.add(("X-Custom", val));
}

Prevention

When it happens

Trigger: Calling the deprecated `.header(key, value)` with a value containing invalid bytes such as `"\n"`, `"\r\n"`, null bytes, or other non-visible ASCII control characters. For example, `.header("X-Test", "\n")` will panic.

Common situations: Embedding user input or multi-line strings into header values without sanitization. Using the deprecated `.header()` method instead of `.add()`.

Related errors


AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09). Data as JSON: /api/errors/57daefdab67a0ae0. Report an issue: GitHub.

Appendix: source

Thrown at actix-web/src/middleware/default_headers.rs:94

    #[doc(hidden)]
    #[deprecated(
        since = "4.0.0",
        note = "Prefer `.add((key, value))`. Will be removed in v5."
    )]
    pub fn header<K, V>(self, key: K, value: V) -> Self
    where
        HeaderName: TryFrom<K>,
        <HeaderName as TryFrom<K>>::Error: Into<HttpError>,
        HeaderValue: TryFrom<V>,
        <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
    {
        self.add((
            HeaderName::try_from(key)
                .map_err(Into::into)
                .expect("Invalid header name"),
            HeaderValue::try_from(value)
                .map_err(Into::into)
                .expect("Invalid header value"),
        ))
    }

    /// Adds a default *Content-Type* header if response does not contain one.
    ///
    /// Default is `application/octet-stream`.
    pub fn add_content_type(self) -> Self {
        #[allow(clippy::declare_interior_mutable_const)]
        const HV_MIME: HeaderValue = HeaderValue::from_static("application/octet-stream");
        self.add((CONTENT_TYPE, HV_MIME))
    }
}

impl<S, B> Transform<S, ServiceRequest> for DefaultHeaders
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
{

View on GitHub (pinned to 4d435abc28)