quarkusio/quarkus · error · IllegalStateException
invalid configuration for a Stork Load Balancer : ${loadBala
Error message
invalid configuration for a Stork Load Balancer : ${loadBalancerConfig} What it means
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.
Source
Thrown at extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/stork/GrpcLoadBalancerProvider.java:88
return NameResolver.ConfigOrError.fromError(Status.INTERNAL);
}
return NameResolver.ConfigOrError
.fromConfig(new StorkLoadBalancerConfig(serviceName));
}
@Override
public LoadBalancer newLoadBalancer(LoadBalancer.Helper helper) {
return new LoadBalancer() {
String serviceName;
@Override
public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
List<EquivalentAddressGroup> addresses = resolvedAddresses.getAddresses();
Object loadBalancerConfig = resolvedAddresses.getLoadBalancingPolicyConfig();
if (!(loadBalancerConfig instanceof StorkLoadBalancerConfig)) {
throw new IllegalStateException("invalid configuration for a Stork Load Balancer : " + loadBalancerConfig);
}
StorkLoadBalancerConfig config = (StorkLoadBalancerConfig) loadBalancerConfig;
Map<ServiceInstance, Subchannel> subChannels = new TreeMap<>(Comparator.comparingLong(ServiceInstance::getId));
Set<ServiceInstance> activeSubchannels = Collections.newSetFromMap(new ConcurrentHashMap<>());
AtomicReference<ConnectivityState> state = new AtomicReference<>(ConnectivityState.CONNECTING);
serviceName = config.serviceName;
final StorkSubchannelPicker picker = new StorkSubchannelPicker(subChannels, serviceName, activeSubchannels);
for (EquivalentAddressGroup addressGroup : addresses) {
ServiceInstance serviceInstance = addressGroup.getAttributes()
.get(GrpcStorkServiceDiscovery.SERVICE_INSTANCE);
CreateSubchannelArgs subChannelArgs = CreateSubchannelArgs.newBuilder()
.setAddresses(addressGroup)
.setAttributes(addressGroup.getAttributes())View on GitHub (pinned to e1c734241f)
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.
Example fix
// before (application.properties) quarkus.grpc.clients.hello.load-balancing-policy=stork // after quarkus.grpc.clients.hello.name-resolver=stork quarkus.stork.hello.service-discovery.type=static quarkus.stork.hello.service-discovery.address-list=localhost:8084
Defensive patterns
Strategy: validation
Validate before calling
// application.properties sanity check before startup // do NOT set quarkus.grpc.clients.<name>.load-balancing-policy=stork manually; // instead set the name resolver: // quarkus.grpc.clients.<name>.name-resolver=stork // and define quarkus.stork.<service>.service-discovery.*
Try / catch
try {
greeter.sayHello(request).await().indefinitely();
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("Stork Load Balancer")) {
log.error("Channel not built by the Quarkus Stork integration; check name-resolver=stork and quarkus-stork deps");
} else { throw e; }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No service definition for serviceName ${serviceName} found.
- gRPC client '${name}' cannot use both domain-socket and Stor
- Invalid @GrpcClient `${targetInfo}` - client name cannot be
- Failed to determine working socket addresses for service-nam
- Unable to find the GrpcClientConfigProvider
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9d41cbb0f6dbdaae.
Report an issue: GitHub.