{"record":{"id":"9d41cbb0f6dbdaae","repo":"quarkusio/quarkus","slug":"invalid-configuration-for-a-stork-load-balancer","errorCode":null,"errorMessage":"invalid configuration for a Stork Load Balancer : ${loadBalancerConfig}","messagePattern":"invalid configuration for a Stork Load Balancer : (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/stork/GrpcLoadBalancerProvider.java","lineNumber":88,"sourceCode":"            return NameResolver.ConfigOrError.fromError(Status.INTERNAL);\n        }\n        return NameResolver.ConfigOrError\n                .fromConfig(new StorkLoadBalancerConfig(serviceName));\n    }\n\n    @Override\n    public LoadBalancer newLoadBalancer(LoadBalancer.Helper helper) {\n        return new LoadBalancer() {\n\n            String serviceName;\n\n            @Override\n            public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {\n                List<EquivalentAddressGroup> addresses = resolvedAddresses.getAddresses();\n\n                Object loadBalancerConfig = resolvedAddresses.getLoadBalancingPolicyConfig();\n                if (!(loadBalancerConfig instanceof StorkLoadBalancerConfig)) {\n                    throw new IllegalStateException(\"invalid configuration for a Stork Load Balancer : \" + loadBalancerConfig);\n                }\n\n                StorkLoadBalancerConfig config = (StorkLoadBalancerConfig) loadBalancerConfig;\n\n                Map<ServiceInstance, Subchannel> subChannels = new TreeMap<>(Comparator.comparingLong(ServiceInstance::getId));\n                Set<ServiceInstance> activeSubchannels = Collections.newSetFromMap(new ConcurrentHashMap<>());\n                AtomicReference<ConnectivityState> state = new AtomicReference<>(ConnectivityState.CONNECTING);\n\n                serviceName = config.serviceName;\n\n                final StorkSubchannelPicker picker = new StorkSubchannelPicker(subChannels, serviceName, activeSubchannels);\n\n                for (EquivalentAddressGroup addressGroup : addresses) {\n                    ServiceInstance serviceInstance = addressGroup.getAttributes()\n                            .get(GrpcStorkServiceDiscovery.SERVICE_INSTANCE);\n                    CreateSubchannelArgs subChannelArgs = CreateSubchannelArgs.newBuilder()\n                            .setAddresses(addressGroup)\n                            .setAttributes(addressGroup.getAttributes())","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/stork/GrpcLoadBalancerProvider.java#L70-L106","documentation":"The Stork load balancer for gRPC expects the resolved address's load-balancing policy config object to be an instance of StorkLoadBalancerConfig, which is installed by Quarkus when the Stork name resolver wires the policy. If the object is missing or of a different type, the channel state is inconsistent (typically the Stork LB policy was not properly registered for this channel) and handleResolvedAddresses throws IllegalStateException.","triggerScenarios":"A gRPC channel is configured with the 'stork' load-balancing policy ('stork' name resolver) but handleResolvedAddresses receives resolvedAddresses.getLoadBalancingPolicyConfig() that is not a StorkLoadBalancerConfig — e.g. the resolver produced addresses without attaching Stork's policy config, or the policy name is set to 'stork' without the Quarkus Stork gRPC integration on the classpath.","commonSituations":"Manually forcing loadBalancingPolicy=stork in a plain grpc config; mixing Quarkus versions where grpc-stork integration JARs mismatch; using Stork service discovery without quarkus-stork dependency registration so the policy config object is a different type.","solutions":["Do not set the load-balancing policy manually; rely on quarkus.grpc.clients.<name>.name-resolver=stork and let Quarkus install the Stork policy.","Add/align the io.quarkus:quarkus-stork and smallrye-stork dependencies; avoid mixing incompatible versions.","Ensure the service is defined in Stork (quarkus.stork.<service>.* discovery config) so the resolver attaches a StorkLoadBalancerConfig.","If using a custom NameResolver, make sure it passes a StorkLoadBalancerConfig as the load-balancing policy config."],"exampleFix":"// before (application.properties)\nquarkus.grpc.clients.hello.load-balancing-policy=stork\n\n// after\nquarkus.grpc.clients.hello.name-resolver=stork\nquarkus.stork.hello.service-discovery.type=static\nquarkus.stork.hello.service-discovery.address-list=localhost:8084","handlingStrategy":"validation","validationCode":"// application.properties sanity check before startup\n// do NOT set quarkus.grpc.clients.<name>.load-balancing-policy=stork manually;\n// instead set the name resolver:\n// quarkus.grpc.clients.<name>.name-resolver=stork\n// and define quarkus.stork.<service>.service-discovery.*","typeGuard":null,"tryCatchPattern":"try {\n    greeter.sayHello(request).await().indefinitely();\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Stork Load Balancer\")) {\n        log.error(\"Channel not built by the Quarkus Stork integration; check name-resolver=stork and quarkus-stork deps\");\n    } else { throw e; }\n}","preventionTips":["Never hand-configure the 'stork' load-balancing policy; use name-resolver=stork.","Keep quarkus-stork and smallrye-stork versions aligned with the Quarkus BOM.","Smoke-test Stork channels at startup with a health-check call."],"tags":["grpc","stork","load-balancer","configuration"],"backgroundTag":"stork-load-balancer-config-invalid","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}