hyperium/hyper · error · std::io::Error
Invalid header name: {:?}
Error message
Invalid header name: {:?} What it means
Thrown by decode_trailers (src/proto/h1/decode.rs:650) when a parsed trailer header's name fails HeaderName::try_from — i.e. it contains characters not allowed in HTTP field names (only visible VCHAR excluding ':' is permitted). The offending header is included in the message via {:?}. Reported as io::ErrorKind::InvalidInput.
Source
Thrown at src/proto/h1/decode.rs:650
"Invalid chunk end LF",
))),
}
}
}
// TODO: disallow Transfer-Encoding, Content-Length, Trailer, etc in trailers ??
fn decode_trailers(buf: &mut BytesMut, count: usize) -> Result<HeaderMap, io::Error> {
let mut trailers = HeaderMap::new();
let mut headers = vec![httparse::EMPTY_HEADER; count];
let res = httparse::parse_headers(buf, &mut headers);
match res {
Ok(httparse::Status::Complete((_, headers))) => {
for header in headers {
use std::convert::TryFrom;
let name = match HeaderName::try_from(header.name) {
Ok(name) => name,
Err(_) => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("Invalid header name: {:?}", &header),
));
}
};
let value = match HeaderValue::from_bytes(header.value) {
Ok(value) => value,
Err(_) => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("Invalid header value: {:?}", &header),
));
}
};
trailers.append(name, value);
}View on GitHub (pinned to 084473f728)
Solutions
- Sanitize trailer names on the sending side: ASCII tokens, no spaces, no colon, typically lower-case kebab.
- Reject/redirect upstream metadata that isn't a valid HTTP field name instead of forwarding it as a trailer.
- Log the offending header (it appears in the error) to identify which peer/component produced it.
Example fix
// before: forwarding arbitrary metadata as a trailer
let name = format!("{}", raw_key); // may contain spaces/unicode
write!(w, "0\r\n{}: {}\r\n\r\n", name, val).await?; // -> error 32
// after: validate/sanitize the field name
fn trailer_name(raw: &str) -> Option<&str> {
let r = raw.as_bytes();
r.iter().all(|b| b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_'))
.then_some(raw)
}
if let Some(n) = trailer_name(&raw_key) {
write!(w, "0\r\n{}: {}\r\n\r\n", n, val).await?;
} Defensive patterns
Strategy: validation
Validate before calling
// Validate trailer names before emitting them: HTTP token chars only.
fn valid_trailer_name(name: &str) -> bool {
!name.is_empty() && name.as_bytes().iter().all(|b| {
matches!(b,
b'!' | b'#' | b'$' | b'%' | b'&' | b'\'' | b'*' | b'+'
| b'-' | b'.' | b'^' | b'_' | b'`' | b'|' | b'~'
| b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z')
})
}
if valid_trailer_name(&key) {
write!(w, "0\r\n{}: {}\r\n\r\n", key, val).await?;
} Type guard
fn valid_trailer_name(name: &str) -> bool {
!name.is_empty() && name.as_bytes().iter().all(|b| {
matches!(b,
b'!' | b'#'..=b'\'' | b'*' | b'+' | b'-' | b'.' | b'^'..=b'`' | b'|' | b'~'
| b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z')
})
} Try / catch
Some(Err(e)) => {
if e.to_string().contains("Invalid header name") {
tracing::warn!(error=%e, "peer sent trailer with illegal field name");
break;
}
return Err(e.into());
} Prevention
- Restrict trailer names to RFC 7230 token characters; reject others at the trust boundary.
- Don't forward arbitrary upstream metadata as trailers; map/sanitize first.
- Log the offending header shown in the error to locate the misbehaving peer.
When it happens
Trigger: A trailer block whose header name is illegal, e.g. "X Bad: 1\r\n" (space in name), "X-Trace\r\n" (no colon treated as invalid by httparse and surfaced here), or a non-ASCII field name like a UTF-8 label.
Common situations: A proxy injecting malformed trailer names; UTF-8 metadata from an upstream system placed verbatim into trailers; gRPC metadata keys that violate HTTP token rules (e.g. uppercase or spaces).
Related errors
- Invalid header value: {:?}
- Partial header
- chunk trailers count overflow
- Invalid trailer end LF
- Invalid chunk size line: missing size digit
AI-assisted analysis of hyperium/hyper@084473f728 (2026-08-06).
Data as JSON: /data/errors/c75548b51a89a801.json.
Report an issue: GitHub.