{"record":{"id":"bfa7793acec4f58d","repo":"grpc/grpc-java","slug":"httpconnectionmanager-with-xff-num-trusted-hops-un","errorCode":null,"errorMessage":"HttpConnectionManager with xff_num_trusted_hops unsupported","messagePattern":"HttpConnectionManager with xff_num_trusted_hops unsupported","errorType":"exception","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsListenerResource.java","lineNumber":499,"sourceCode":"        throw new ResourceInvalidException(\"Unknown source-type: \" + proto.getSourceType());\n    }\n    return FilterChainMatch.create(\n        proto.getDestinationPort().getValue(),\n        prefixRanges.build(),\n        ImmutableList.copyOf(proto.getApplicationProtocolsList()),\n        sourcePrefixRanges.build(),\n        sourceType,\n        ImmutableList.copyOf(proto.getSourcePortsList()),\n        ImmutableList.copyOf(proto.getServerNamesList()),\n        proto.getTransportProtocol());\n  }\n\n  @VisibleForTesting\n  static io.grpc.xds.HttpConnectionManager parseHttpConnectionManager(\n      HttpConnectionManager proto, FilterRegistry filterRegistry,\n      boolean isForClient, XdsResourceType.Args args) throws ResourceInvalidException {\n    if (proto.getXffNumTrustedHops() != 0) {\n      throw new ResourceInvalidException(\n          \"HttpConnectionManager with xff_num_trusted_hops unsupported\");\n    }\n    if (!proto.getOriginalIpDetectionExtensionsList().isEmpty()) {\n      throw new ResourceInvalidException(\"HttpConnectionManager with \"\n          + \"original_ip_detection_extensions unsupported\");\n    }\n    // Obtain max_stream_duration from Http Protocol Options.\n    long maxStreamDuration = 0;\n    if (proto.hasCommonHttpProtocolOptions()) {\n      HttpProtocolOptions options = proto.getCommonHttpProtocolOptions();\n      if (options.hasMaxStreamDuration()) {\n        maxStreamDuration = Durations.toNanos(options.getMaxStreamDuration());\n      }\n    }\n\n    // Parse http filters.\n    if (proto.getHttpFiltersList().isEmpty()) {\n      throw new ResourceInvalidException(\"Missing HttpFilter in HttpConnectionManager.\");","sourceCodeStart":481,"sourceCodeEnd":517,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsListenerResource.java#L481-L517","documentation":"gRPC xDS does not implement xff_num_trusted_hops on the HttpConnectionManager, which controls how many trusted proxy hops are counted when interpreting X-Forwarded-For. If the field is nonzero the HCM is considered unsupported and a ResourceInvalidException is thrown, rejecting the Listener.","triggerScenarios":"Listener's http_connection_manager has xff_num_trusted_hops set to a nonzero value, detected in parseHttpConnectionManager (invoked from processClientSideListener or httpConnectionManager parsing).","commonSituations":"Envoy configs deployed behind multiple load balancers where operators set trusted hops to make XFF parsing correct, shared Envoy templates reused for gRPC xDS listeners, or control planes that propagate the field unconditionally.","solutions":["Remove xff_num_trusted_hops (or set it to 0) from the http_connection_manager.","Handle X-Forwarded-For interpretation at an upstream proxy/Envoy layer instead of the gRPC client.","Split the config so Envoy-managed listeners keep the setting while gRPC-consumed resources do not."],"exampleFix":"// before\nhttp_connection_manager: { xff_num_trusted_hops: 2, ... }\n// after\nhttp_connection_manager: { ... }","handlingStrategy":"validation","validationCode":"if (hcm.getXffNumTrustedHops() != 0) {\n  throw new IllegalArgumentException(\"xff_num_trusted_hops unsupported by grpc xds\");\n}","typeGuard":null,"tryCatchPattern":"try { applyResource(listener) } catch (ResourceInvalidException e) { if (e.getMessage().contains(\"xff_num_trusted_hops\")) resubmitWithoutXffHops(); }","preventionTips":["Strip xff_num_trusted_hops from resources destined for gRPC xDS clients","Keep separate Envoy vs gRPC listener templates","Validate against gRPC's supported-field allowlist in the control plane"],"tags":["grpc","xds","http","unsupported-feature"],"backgroundTag":"unsupported-config-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"}