{"record":{"id":"76e9d4d4e893ad26","repo":"grpc/grpc-go","slug":"malformed-binary-metadata-q-in-header-q-v","errorCode":null,"errorMessage":"malformed binary metadata %q in header %q: %v","messagePattern":"malformed binary metadata %q in header %q: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/transport/handler_server.go","lineNumber":129,"sourceCode":"\t\t}\n\t\tst.timeoutSet = true\n\t\tst.timeout = to\n\t}\n\n\tmetakv := []string{\"content-type\", contentType}\n\tif r.Host != \"\" {\n\t\tmetakv = append(metakv, \":authority\", r.Host)\n\t}\n\tfor k, vv := range r.Header {\n\t\tk = strings.ToLower(k)\n\t\tif isReservedHeader(k) && !isWhitelistedHeader(k) {\n\t\t\tcontinue\n\t\t}\n\t\tfor _, v := range vv {\n\t\t\tv, err := decodeMetadataHeader(k, v)\n\t\t\tif err != nil {\n\t\t\t\tmsg := fmt.Sprintf(\"malformed binary metadata %q in header %q: %v\", v, k, err)\n\t\t\t\thttp.Error(w, msg, http.StatusBadRequest)\n\t\t\t\treturn nil, status.Error(codes.Internal, msg)\n\t\t\t}\n\t\t\tmetakv = append(metakv, k, v)\n\t\t}\n\t}\n\tst.headerMD = metadata.Pairs(metakv...)\n\n\treturn st, nil\n}\n\n// serverHandlerTransport is an implementation of ServerTransport\n// which replies to exactly one gRPC request (exactly one HTTP request),\n// using the net/http.Handler interface. This http.Handler is guaranteed\n// at this point to be speaking over HTTP/2, so it's able to speak valid\n// gRPC.\ntype serverHandlerTransport struct {\n\trw         http.ResponseWriter\n\treq        *http.Request","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/transport/handler_server.go#L111-L147","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: a custom binary header set without base64\n//   x-auth-bin: <raw bytes>\n// server: malformed binary metadata\n\n// after: base64-encode binary header values\nimport \"encoding/base64\"\nh.Set(\"x-auth-bin\", base64.StdEncoding.EncodeToString(rawBytes))","handlingStrategy":"validation","validationCode":"// Validate that any -bin header is valid base64 before forwarding\nimport (\"encoding/base64\"; \"strings\")\nfunc validBinHeader(k, v string) bool {\n    if !strings.HasSuffix(k, \"-bin\") { return true }\n    _, err := base64.StdEncoding.DecodeString(v)\n    return err == nil\n}","typeGuard":null,"tryCatchPattern":"// NewServerHandlerTransport returns this as an error; respond and abort\nst, err := transport.NewServerHandlerTransport(w, r, stats, pool)\nif err != nil {\n    // HTTP 400 already written for malformed binary metadata\n    return\n}","preventionTips":["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."],"tags":["transport","http","metadata","base64","grpc-go","handler"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}