{"id":"81e03350ff74c9ed","repo":"hyperium/hyper","slug":"invalid-header-value","errorCode":null,"errorMessage":"Invalid header value: {:?}","messagePattern":"Invalid header value: (.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"src/proto/h1/decode.rs","lineNumber":660,"sourceCode":"    let res = httparse::parse_headers(buf, &mut headers);\n    match res {\n        Ok(httparse::Status::Complete((_, headers))) => {\n            for header in headers {\n                use std::convert::TryFrom;\n                let name = match HeaderName::try_from(header.name) {\n                    Ok(name) => name,\n                    Err(_) => {\n                        return Err(io::Error::new(\n                            io::ErrorKind::InvalidInput,\n                            format!(\"Invalid header name: {:?}\", &header),\n                        ));\n                    }\n                };\n\n                let value = match HeaderValue::from_bytes(header.value) {\n                    Ok(value) => value,\n                    Err(_) => {\n                        return Err(io::Error::new(\n                            io::ErrorKind::InvalidInput,\n                            format!(\"Invalid header value: {:?}\", &header),\n                        ));\n                    }\n                };\n\n                trailers.append(name, value);\n            }\n\n            Ok(trailers)\n        }\n        Ok(httparse::Status::Partial) => Err(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            \"Partial header\",\n        )),\n        Err(e) => Err(io::Error::new(io::ErrorKind::InvalidInput, e)),\n    }\n}","sourceCodeStart":642,"sourceCodeEnd":678,"githubUrl":"https://github.com/hyperium/hyper/blob/084473f728f9d07b3be5845475aa2f62ed9ff579/src/proto/h1/decode.rs#L642-L678","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: raw newline in trailer value\nwrite!(w, \"0\\r\\nx-log: a\\nb\\r\\n\\r\\n\").await?; // -> error 33\n\n// after: encode the value\nlet v = base64::encode(b\"a\\nb\");\nwrite!(w, \"0\\r\\nx-log: {}\\r\\n\\r\\n\", v).await?;","handlingStrategy":"validation","validationCode":"// Reject/encode non-ASCII or control bytes in trailer values before sending.\nfn safe_trailer_value(v: &str) -> Option<String> {\n    v.is_ascii() && v.bytes().all(|b| b == b'\\t' || b == b' ' || (0x21..=0x7e).contains(&b))\n        .then(|| v.to_string())\n        .or_else(|| Some(base64::encode(v.as_bytes())))\n}\nwrite!(w, \"0\\r\\nx-log: {}\\r\\n\\r\\n\", safe_trailer_value(&raw).unwrap()).await?;","typeGuard":"fn is_printable_ascii_value(v: &str) -> bool {\n    v.bytes().all(|b| b == b'\\t' || b == b' ' || (0x21..=0x7e).contains(&b))\n}","tryCatchPattern":"Some(Err(e)) => {\n    if e.to_string().contains(\"Invalid header value\") {\n        tracing::warn!(error=%e, \"peer sent trailer with illegal field value\");\n        break;\n    }\n    return Err(e.into());\n}","preventionTips":["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."],"tags":["http","http1","chunked","trailers","headers","hyper","rust"],"analyzedSha":"084473f728f9d07b3be5845475aa2f62ed9ff579","analyzedAt":"2026-08-06T01:20:18.522Z","schemaVersion":2}