{"record":{"id":"6ca0791b789aa40d","repo":"grpc/grpc-java","slug":"invalid-header-name-headername","errorCode":null,"errorMessage":"Invalid header name: ${headerName}","messagePattern":"Invalid header name: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/matcher/HeaderMatchInput.java","lineNumber":58,"sourceCode":"  HeaderMatchInput(String headerName) {\n    this.headerName = checkNotNull(headerName, \"headerName\");\n    if (headerName.isEmpty() || headerName.length() >= 16384) {\n      throw new IllegalArgumentException(\n          \"Header name length must be in range [1, 16384): \" + headerName.length());\n    }\n    if (!headerName.equals(headerName.toLowerCase(Locale.ROOT))) {\n      throw new IllegalArgumentException(\"Header name must be lowercase: \" + headerName);\n    }\n    try {\n      if (headerName.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {\n        this.binaryKey = Metadata.Key.of(headerName, Metadata.BINARY_BYTE_MARSHALLER);\n        this.stringKey = null;\n      } else {\n        this.binaryKey = null;\n        this.stringKey = Metadata.Key.of(headerName, Metadata.ASCII_STRING_MARSHALLER);\n      }\n    } catch (IllegalArgumentException e) {\n      throw new IllegalArgumentException(\"Invalid header name: \" + headerName, e);\n    }\n  }\n    \n  @Override\n  public String apply(MatchContext context) {\n    if (\"te\".equals(headerName)) {\n      return null;\n    }\n    if (binaryKey != null) {\n      Iterable<byte[]> values = context.getMetadata().getAll(binaryKey);\n      if (values == null) {\n        return null;\n      }\n      StringBuilder sb = new StringBuilder();\n      boolean first = true;\n      for (byte[] value : values) {\n        if (!first) {\n          sb.append(\",\");","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/matcher/HeaderMatchInput.java#L40-L76","documentation":"HeaderMatchInput validates an xDS header name by constructing a Metadata.Key; if the name is not a valid gRPC metadata key (must be lowercase ASCII letters, digits, hyphen, underscore, and dot), the underlying IllegalArgumentException is rethrown wrapped with the offending header name. This prevents invalid header names from silently failing to match at runtime.","triggerScenarios":"Calling getInput with a TypedExtensionConfig whose HttpRequestHeaderMatchInput.header_name contains characters invalid for gRPC metadata keys (e.g. uppercase letters, spaces, colons) or is empty.","commonSituations":"Copy-pasting Envoy route config with HTTP-style header names like 'X-Request-Id' (uppercase not allowed for metadata keys) or hand-written CEL/rbac matcher configs with typos in the header name.","solutions":["Check the header_name in the xDS HttpHeaderMatchInput config: it must be lowercase and only contain letters, digits, '-', '_', '.'.","Lowercase and sanitize the header name (e.g. X-Request-Id -> x-request-id).","If the name is dynamic, validate it before building the matcher with a regex like ^[a-z0-9_.-]+$."],"exampleFix":"// before\n{\"header_name\": \"X-Request-Id\"}\n// after\n{\"header_name\": \"x-request-id\"}","handlingStrategy":"validation","validationCode":"static boolean isValidHeaderName(String name) {\n  return name != null && name.matches(\"^[a-z0-9_.-]+$\");\n}\nif (!isValidHeaderName(cfg.getHeaderName())) throw new IllegalArgumentException(\"bad header name: \" + cfg.getHeaderName());","typeGuard":"static boolean isValidHeaderName(String name) {\n  return name != null && name.matches(\"^[a-z0-9_.-]+$\");\n}","tryCatchPattern":"try {\n  input = factory.getInput(config);\n} catch (IllegalArgumentException e) {\n  logger.warn(\"bad header match input: \" + e.getMessage());\n  throw new StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription(e.getMessage()));\n}","preventionTips":["Always lowercase header names in generated xDS configs","Validate header_name against ^[a-z0-9_.-]+$ before sending config","Reject invalid headers at the management server, not just the client"],"tags":["xds","grpc","config-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"}