{"record":{"id":"31bcb856899081b6","repo":"grpc/grpc-java","slug":"filter-chain-names-must-be-unique-found-duplicate","errorCode":null,"errorMessage":"Filter chain names must be unique. Found duplicate: ${filterChainName}","messagePattern":"Filter chain names must be unique\\. Found duplicate: (.+?)","errorType":"validation","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsListenerResource.java","lineNumber":195,"sourceCode":"          break;\n        default:\n          // noop\n      }\n    }\n\n    ImmutableList.Builder<FilterChain> filterChains = ImmutableList.builder();\n    Set<String> filterChainNames = new HashSet<>();\n    Set<FilterChainMatch> filterChainMatchSet = new HashSet<>();\n    int i = 0;\n    for (io.envoyproxy.envoy.config.listener.v3.FilterChain fc : proto.getFilterChainsList()) {\n      // May be empty. If it's not empty, required to be unique.\n      String filterChainName = fc.getName();\n      if (filterChainName.isEmpty()) {\n        // Generate a name, so we can identify it in the logs.\n        filterChainName = \"chain_\" + i;\n      }\n      if (!filterChainNames.add(filterChainName)) {\n        throw new ResourceInvalidException(\"Filter chain names must be unique. \"\n            + \"Found duplicate: \" + filterChainName);\n      }\n      filterChains.add(\n          parseFilterChain(fc, filterChainName, tlsContextManager, filterRegistry,\n              filterChainMatchSet, certProviderInstances, args));\n      i++;\n    }\n\n    FilterChain defaultFilterChain = null;\n    if (proto.hasDefaultFilterChain()) {\n      String defaultFilterChainName = proto.getDefaultFilterChain().getName();\n      if (defaultFilterChainName.isEmpty()) {\n        defaultFilterChainName = \"chain_default\";\n      }\n      defaultFilterChain = parseFilterChain(\n          proto.getDefaultFilterChain(), defaultFilterChainName, tlsContextManager, filterRegistry,\n          null, certProviderInstances, args);\n    }","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsListenerResource.java#L177-L213","documentation":"Each FilterChain in a server-side Listener must have a unique non-empty name so gRPC can identify filter chains in logs and match logic. The parser collects names into a set and throws ResourceInvalidException when a duplicate is added. Resources with duplicate filter chain names are considered invalid and rejected.","triggerScenarios":"A Listener proto contains two or more filter_chains entries whose name field is identical (e.g. both set to 'fc1', or both explicitly set to the same string) while processing parseServerSideListener.","commonSituations":"Copy-pasted filter chain blocks in Envoy-style configs where the name field was left identical; control planes that auto-generate filter chains without unique naming; hand-edited LDS resources.","solutions":["Give each filter_chain in the Listener a distinct name in the control plane config","Leave the name field empty (the parser auto-generates unique names 'chain_0', 'chain_1', ...) instead of duplicating names","Audit the LDS resource JSON/YAML for repeated filter_chain name values and rename them"],"exampleFix":"# before\nfilter_chains:\n- name: fc1\n  ...\n- name: fc1\n  ...\n# after\nfilter_chains:\n- name: fc1\n  ...\n- name: fc2\n  ...","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (FilterChain fc : listener.getFilterChainsList()) {\n  if (!seen.add(fc.getName())) {\n    throw new IllegalArgumentException(\"Duplicate filter chain name: \" + fc.getName());\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  listener = XdsListenerResource.parseServerSideListener(proto, ...);\n} catch (ResourceInvalidException e) {\n  if (e.getMessage().startsWith(\"Filter chain names must be unique\")) {\n    logger.warn(\"Rename duplicated filter chain in LDS resource\", e);\n  }\n}","preventionTips":["Enforce unique, meaningful filter chain names at the control plane","Prefer leaving names empty (auto-generated) over duplicating them","Include filter chain names in control-plane CI validation"],"tags":["xds","grpc","config-validation","duplicate"],"backgroundTag":"invalid-config-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}