hyperium/hyper · error · std::io::Error
Invalid header value: {:?}
Error message
Invalid header value: {:?} What it means
Thrown by decode_trailers (src/proto/h1/decode.rs:660) when a trailer's value fails HeaderValue::from_bytes — HTTP field values may contain only visible ASCII plus spaces and tabs (no raw control bytes, no NUL). The offending header is formatted into the message via {:?}. Reported as io::ErrorKind::InvalidInput.
Source
Thrown at src/proto/h1/decode.rs:660
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);
}
Ok(trailers)
}
Ok(httparse::Status::Partial) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Partial header",
)),
Err(e) => Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
}
}View on GitHub (pinned to 084473f728)
Solutions
- Base64- or percent-encode binary/UTF-8 trailer values before sending.
- Strip CR/LF/NUL and other control bytes from any dynamic trailer value.
- Keep trailer values to visible ASCII; move large/binary metadata into the body.
Example fix
// before: raw newline in trailer value
write!(w, "0\r\nx-log: a\nb\r\n\r\n").await?; // -> error 33
// after: encode the value
let v = base64::encode(b"a\nb");
write!(w, "0\r\nx-log: {}\r\n\r\n", v).await?; Defensive patterns
Strategy: validation
Validate before calling
// Reject/encode non-ASCII or control bytes in trailer values before sending.
fn safe_trailer_value(v: &str) -> Option<String> {
v.is_ascii() && v.bytes().all(|b| b == b'\t' || b == b' ' || (0x21..=0x7e).contains(&b))
.then(|| v.to_string())
.or_else(|| Some(base64::encode(v.as_bytes())))
}
write!(w, "0\r\nx-log: {}\r\n\r\n", safe_trailer_value(&raw).unwrap()).await?; Type guard
fn is_printable_ascii_value(v: &str) -> bool {
v.bytes().all(|b| b == b'\t' || b == b' ' || (0x21..=0x7e).contains(&b))
} Try / catch
Some(Err(e)) => {
if e.to_string().contains("Invalid header value") {
tracing::warn!(error=%e, "peer sent trailer with illegal field value");
break;
}
return Err(e.into());
} Prevention
- Base64- or percent-encode binary/UTF-8 trailer values.
- Strip CR/LF/NUL and control bytes from any dynamic trailer value.
- Keep trailers to visible ASCII; move large/binary data into the body.
When it happens
Trigger: A trailer value containing a control byte, NUL, or a bare CR/LF not part of folded whitespace, e.g. "x-trace: abc\0def\r\n" or a value with a raw newline.
Common situations: Binary/UTF-8 data placed verbatim into a trailer; debug strings with embedded newlines; a logging proxy that copies unescaped stack traces into a trailer value.
Related errors
- Invalid header name: {:?}
- 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/81e03350ff74c9ed.json.
Report an issue: GitHub.