{"record":{"id":"1fc4700474dc54bd","repo":"grpc/grpc-java","slug":"httpconnectionmanager-contains-duplicate-httpfilte","errorCode":null,"errorMessage":"HttpConnectionManager contains duplicate HttpFilter: ${filterName}","messagePattern":"HttpConnectionManager contains duplicate HttpFilter: (.+?)","errorType":"exception","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsListenerResource.java","lineNumber":526,"sourceCode":"    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.\");\n    }\n    List<Filter.NamedFilterConfig> filterConfigs = new ArrayList<>();\n    Set<String> names = new HashSet<>();\n    for (int i = 0; i < proto.getHttpFiltersCount(); i++) {\n      io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter\n          httpFilter = proto.getHttpFiltersList().get(i);\n      String filterName = httpFilter.getName();\n      if (!names.add(filterName)) {\n        throw new ResourceInvalidException(\n            \"HttpConnectionManager contains duplicate HttpFilter: \" + filterName);\n      }\n      StructOrError<Filter.FilterConfig> filterConfig =\n          parseHttpFilter(httpFilter, filterRegistry, isForClient, args);\n      if ((i == proto.getHttpFiltersCount() - 1)\n          && (filterConfig == null || !isTerminalFilter(filterConfig.getStruct()))) {\n        throw new ResourceInvalidException(\"The last HttpFilter must be a terminal filter: \"\n            + filterName);\n      }\n      if (filterConfig == null) {\n        continue;\n      }\n      if (filterConfig.getErrorDetail() != null) {\n        throw new ResourceInvalidException(\n            \"HttpConnectionManager contains invalid HttpFilter: \"\n                + filterConfig.getErrorDetail());\n      }\n      if ((i < proto.getHttpFiltersCount() - 1) && isTerminalFilter(filterConfig.getStruct())) {","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsListenerResource.java#L508-L544","documentation":"Each HttpFilter name within an HttpConnectionManager must be unique because filter names are used as keys into the per-filter config map. A duplicate name is ambiguous, so XdsListenerResource throws ResourceInvalidException naming the duplicated filter.","triggerScenarios":"http_filters list containing two HttpFilter entries with the same name field, detected via the names HashSet inside the parse loop in parseHttpConnectionManager.","commonSituations":"Merging/concatenating filter lists from multiple sources (base + overlay config) without deduplicating names, control-plane merge bugs, or copy-paste of a filter block (e.g. two 'envoy.filters.http.router' entries or two instances of the same named filter).","solutions":["Rename one of the duplicate HttpFilters so every name in http_filters is unique.","Remove the redundant duplicate filter entry.","Fix the control-plane merge logic that concatenated two filter lists without deduplication."],"exampleFix":"// before\nhttp_filters: [{ name: router, ... }, { name: router, ... }]\n// after\nhttp_filters: [{ name: envoy.filters.http.router, ... }]","handlingStrategy":"validation","validationCode":"Set<String> names = new HashSet<>();\nfor (HttpFilter f : hcm.getHttpFiltersList()) {\n  if (!names.add(f.getName())) throw new IllegalArgumentException(\"duplicate HttpFilter: \" + f.getName());\n}","typeGuard":null,"tryCatchPattern":"try { applyResource(listener) } catch (ResourceInvalidException e) { if (e.getMessage().contains(\"duplicate HttpFilter\")) dedupeFiltersByName(); }","preventionTips":["Deduplicate by name when merging filter lists from multiple config sources","Never emit the same filter twice (router must appear exactly once, last)","Add a CI lint asserting unique HttpFilter names"],"tags":["grpc","xds","http","config-validation"],"backgroundTag":"conflicting-config-options","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"}