{"record":{"id":"b3910e221f4a89fe","repo":"grpc/grpc-java","slug":"found-more-than-one-matching-filter-chains-this-s","errorCode":null,"errorMessage":"Found more than one matching filter chains. This should not be possible as ClientXdsClient validated the chains for uniqueness.","messagePattern":"Found more than one matching filter chains\\. This should not be possible as ClientXdsClient validated the chains for uniqueness\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"xds/src/main/java/io/grpc/xds/FilterChainMatchingProtocolNegotiators.java","lineNumber":189,"sourceCode":"      }\n\n      /**\n       * Throws IllegalStateException when no exact one match, and we should close the connection.\n       */\n      SelectedConfig select(InetSocketAddress localAddr, InetSocketAddress remoteAddr) {\n        Collection<FilterChain> filterChains = routingConfigs.keySet();\n        filterChains = filterOnDestinationPort(filterChains);\n        filterChains = filterOnIpAddress(filterChains, localAddr.getAddress(), true);\n        filterChains = filterOnServerNames(filterChains);\n        filterChains = filterOnTransportProtocol(filterChains);\n        filterChains = filterOnApplicationProtocols(filterChains);\n        filterChains =\n                filterOnSourceType(filterChains, remoteAddr.getAddress(), localAddr.getAddress());\n        filterChains = filterOnIpAddress(filterChains, remoteAddr.getAddress(), false);\n        filterChains = filterOnSourcePort(filterChains, remoteAddr.getPort());\n\n        if (filterChains.size() > 1) {\n          throw new IllegalStateException(\"Found more than one matching filter chains. This should \"\n              + \"not be possible as ClientXdsClient validated the chains for uniqueness.\");\n        }\n        if (filterChains.size() == 1) {\n          FilterChain selected = Iterables.getOnlyElement(filterChains);\n          return new SelectedConfig(\n                  routingConfigs.get(selected), selected.sslContextProviderSupplier());\n        }\n        if (defaultRoutingConfig.get() != null) {\n          return new SelectedConfig(defaultRoutingConfig, defaultSslContextProviderSupplier);\n        }\n        return null;\n      }\n\n      // reject if filer-chain-match has non-empty application_protocols\n      private static Collection<FilterChain> filterOnApplicationProtocols(\n              Collection<FilterChain> filterChains) {\n        ArrayList<FilterChain> filtered = new ArrayList<>(filterChains.size());\n        for (FilterChain filterChain : filterChains) {","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/FilterChainMatchingProtocolNegotiators.java#L171-L207","documentation":"FilterChainMatchingProtocolNegotiators.select filters listener filter chains by destination/source IP and port; after full filtering more than one chain remained, which contradicts ClientXdsClient's uniqueness validation, so an IllegalStateException is thrown. This is an internal invariant violation: by design at most one filter chain should match a connection.","triggerScenarios":"Receiving an LDS listener whose filter chains are indistinguishable after matching on destination port/IP, source IP/port and source type — i.e. ClientXdsClient accepted duplicate/multiple matching chains for the same connection predicate.","commonSituations":"Control plane sends overlapping filter_chain match predicates (e.g. two chains with the same destination port and no distinguishing prefix ranges); ClientXdsClient validation not catching an overlap the runtime matcher exposes; version skew between validation and matching logic.","solutions":["Inspect the LDS listener resource and make filter chain match predicates mutually exclusive (distinct destination_ports/prefix_ranges/source ranges).","File/verify a bug against grpc-java if ClientXdsClient's uniqueness validation should have rejected this listener.","Update both client and management server to versions with consistent filter-chain validation.","Dump the listener config (Envoy admin / Istio debug) and compare the overlapping chains."],"exampleFix":"// before (two overlapping chains)\n{\"filterChainMatch\": {\"destinationPort\": 8080}},\n{\"filterChainMatch\": {\"destinationPort\": 8080}}\n// after — distinct predicates\n{\"filterChainMatch\": {\"destinationPort\": 8080, \"prefixRanges\": [{\"addressPrefix\": \"10.0.0.0\", \"prefixLen\": 8}]}},\n{\"filterChainMatch\": {\"destinationPort\": 8080, \"prefixRanges\": [{\"addressPrefix\": \"10.1.0.0\", \"prefixLen\": 16}]}}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { /* connect via xDS */ } catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"more than one matching filter chains\")) {\n    log.error(\"Listener has overlapping filter chains; fix LDS match predicates\");\n  }\n}","preventionTips":["Make filter_chain match predicates mutually exclusive in the listener config","Upgrade grpc-java/management server together so chain uniqueness validation and matching stay consistent","Reproduce with a dump of the listener resource when it occurs"],"tags":["xds","filter-chain","invariant-violation","listener"],"backgroundTag":"internal-invariant-violation","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"}