grpc/grpc-go · error
malformed binary metadata %q in header %q: %v
Error message
malformed binary metadata %q in header %q: %v
What it means
NewServerHandlerTransport (handler_server.go:53) decodes every incoming header; for keys ending in -bin it base64-decodes the value via decodeBinHeader. If decoding fails it writes HTTP 400 and returns this error (codes.Internal). The error names the offending value and header key.
Source
Thrown at internal/transport/handler_server.go:129
}
st.timeoutSet = true
st.timeout = to
}
metakv := []string{"content-type", contentType}
if r.Host != "" {
metakv = append(metakv, ":authority", r.Host)
}
for k, vv := range r.Header {
k = strings.ToLower(k)
if isReservedHeader(k) && !isWhitelistedHeader(k) {
continue
}
for _, v := range vv {
v, err := decodeMetadataHeader(k, v)
if err != nil {
msg := fmt.Sprintf("malformed binary metadata %q in header %q: %v", v, k, err)
http.Error(w, msg, http.StatusBadRequest)
return nil, status.Error(codes.Internal, msg)
}
metakv = append(metakv, k, v)
}
}
st.headerMD = metadata.Pairs(metakv...)
return st, nil
}
// serverHandlerTransport is an implementation of ServerTransport
// which replies to exactly one gRPC request (exactly one HTTP request),
// using the net/http.Handler interface. This http.Handler is guaranteed
// at this point to be speaking over HTTP/2, so it's able to speak valid
// gRPC.
type serverHandlerTransport struct {
rw http.ResponseWriter
req *http.RequestView on GitHub (pinned to 03255a9237)
Solutions
- Ensure any '-bin' header value is standard base64-encoded (the gRPC wire convention for binary metadata).
- If a proxy rewrites binary headers, verify it preserves/produces valid base64.
- Drop or correctly re-encode the offending header at the edge if it cannot be trusted.
Example fix
// before: a custom binary header set without base64
// x-auth-bin: <raw bytes>
// server: malformed binary metadata
// after: base64-encode binary header values
import "encoding/base64"
h.Set("x-auth-bin", base64.StdEncoding.EncodeToString(rawBytes)) Defensive patterns
Strategy: validation
Validate before calling
// Validate that any -bin header is valid base64 before forwarding
import ("encoding/base64"; "strings")
func validBinHeader(k, v string) bool {
if !strings.HasSuffix(k, "-bin") { return true }
_, err := base64.StdEncoding.DecodeString(v)
return err == nil
} Try / catch
// NewServerHandlerTransport returns this as an error; respond and abort
st, err := transport.NewServerHandlerTransport(w, r, stats, pool)
if err != nil {
// HTTP 400 already written for malformed binary metadata
return
} Prevention
- Always base64-encode any binary metadata header value per the gRPC wire spec.
- Audit proxies/clients that set '-bin' headers to ensure correct encoding.
- Strip malformed binary headers at the trust boundary rather than letting them reach the gRPC server.
When it happens
Trigger: An incoming request carries a header whose key ends in '-bin' (the gRPC binary-metadata convention) but whose value is not valid base64 - e.g. truncated, containing illegal characters, or wrong padding. decodeMetadataHeader (http_util.go:150) -> decodeBinHeader returns the error.
Common situations: A proxy or client sets a binary header (e.g. grpc-status-details-bin, a custom auth-bin) with incorrectly base64-encoded data; a truncated header from an MTU/transfer issue; a non-gRPC producer that didn't base64-encode binary metadata per the gRPC spec.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- gRPC requires a ResponseWriter supporting http.Flusher
- malformed grpc-timeout: %v
- credentials: rawConn is dispatched out of gRPC
- invalid gRPC request method %q
- invalid gRPC request content-type %q
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/76e9d4d4e893ad26.
Report an issue: GitHub.