{"record":{"id":"97530993f3cd3186","repo":"grpc/grpc-java","slug":"invalid-header-key","errorCode":null,"errorMessage":"Invalid header key: ","messagePattern":"Invalid header key: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/grpcservice/HeaderValueValidationUtils.java","lineNumber":36,"sourceCode":"\nimport com.google.protobuf.ByteString;\nimport java.util.Locale;\n\n/**\n * Utility class for validating HTTP headers.\n */\npublic final class HeaderValueValidationUtils {\n  public static final int MAX_HEADER_LENGTH = 16384;\n\n  private HeaderValueValidationUtils() {}\n\n  /**\n   * Validates that the header key is non-empty and within allowed length.\n   * Throws {@link IllegalArgumentException} if invalid.\n   */\n  public static void validateHeaderKey(String key) {\n    if (key == null || key.isEmpty() || key.length() > MAX_HEADER_LENGTH) {\n      throw new IllegalArgumentException(\"Invalid header key: \" + key);\n    }\n  }\n\n  /**\n   * Validates that the header value is within allowed length and contains valid ASCII characters.\n   * Throws {@link IllegalArgumentException} if invalid.\n   */\n  public static void validateHeaderValue(String key, String value) {\n    validateHeaderKey(key);\n    if (value == null || value.length() > MAX_HEADER_LENGTH) {\n      throw new IllegalArgumentException(\"Header value length exceeds maximum allowed length\");\n    }\n    if (!key.endsWith(\"-bin\") && !isValidAsciiHeaderValue(value)) {\n      throw new IllegalArgumentException(\n          \"Invalid ASCII characters in header value for key: \" + key);\n    }\n  }\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/grpcservice/HeaderValueValidationUtils.java#L18-L54","documentation":"HeaderValueValidationUtils.validateHeaderKey checks that a header key is non-null, non-empty, and within MAX_HEADER_LENGTH. Keys violating these rules cause an IllegalArgumentException including the offending key. It guards HTTP/2 header-name rules before ext_proc mutations are applied.","triggerScenarios":"validateHeaderKey (directly or via validateHeaderValue) receives a null key, an empty \"\" key, or a key longer than MAX_HEADER_LENGTH — typically from an ext_proc header-mutation response.","commonSituations":"ext_proc server returning HeaderValue protos with unset key; middleware constructing headers programmatically and forgetting the name; config-driven header injection with a blank key template.","solutions":["Fix the ext_proc server so every HeaderValue carries a valid, non-empty key within the length limit","Validate/sanitize keys on the mutation producer before returning them","Reject or log-and-skip invalid header mutations in your processor logic","Keep header names short and lowercase per HTTP/2 conventions"],"exampleFix":"// before\nHeaderValue.newBuilder().setValue(\"abc\").build() // missing key\n// after\nHeaderValue.newBuilder().setKey(\"x-user-id\").setValue(\"abc\").build()","handlingStrategy":"validation","validationCode":"if (key == null || key.isEmpty() || key.length() > HeaderValueValidationUtils.MAX_HEADER_LENGTH) { rejectMutation(); }","typeGuard":"null","tryCatchPattern":"try { HeaderValueValidationUtils.validateHeaderKey(key); }\ncatch (IllegalArgumentException e) { log.warn(\"Dropping invalid header mutation\", e); }","preventionTips":["Always set a valid key on HeaderValue protos","Validate header names before returning ext_proc mutations","Follow HTTP/2 header-name rules (lowercase, no spaces)"],"tags":["xds","extproc","headers","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}