grpc/grpc-java · error · XdsInitializationException
Caller failed to initialize XDS_CLIENT_SUPPLIER
Error message
Caller failed to initialize XDS_CLIENT_SUPPLIER
What it means
XdsNameResolver's XdsClient supplier was never initialized: the holder's get() returned null, meaning the caller was expected to set XDS_CLIENT_SUPPLIER (typically via an injected supplier in tests or embedded usage) but did not. This is an internal initialization guard surfaced as XdsInitializationException.
Source
Thrown at xds/src/main/java/io/grpc/xds/XdsNameResolver.java:1121
@Override
public XdsClient returnObject(XdsClient xdsClient) {
return xdsClientPool.returnObject(xdsClient);
}
}
private static final class SupplierXdsClientPool implements XdsClientPool {
private final Supplier<XdsClient> xdsClientSupplier;
SupplierXdsClientPool(Supplier<XdsClient> xdsClientSupplier) {
this.xdsClientSupplier = checkNotNull(xdsClientSupplier, "xdsClientSupplier");
}
@Override
public XdsClient getObject() throws XdsInitializationException {
XdsClient xdsClient = xdsClientSupplier.get();
if (xdsClient == null) {
throw new XdsInitializationException("Caller failed to initialize XDS_CLIENT_SUPPLIER");
}
return xdsClient;
}
@Override
public XdsClient returnObject(XdsClient xdsClient) {
return null;
}
}
static final class RawMessageClientInterceptor implements ClientInterceptor {
private static final MethodDescriptor.Marshaller<InputStream> RAW_MARSHALLER =
new MethodDescriptor.Marshaller<InputStream>() {
@Override
public InputStream stream(InputStream value) {
return value;
}
View on GitHub (pinned to 64daddc1f3)
Solutions
- Use the standard XdsNameResolverProvider / xDS bootstrapping path instead of constructing XdsNameResolver directly
- In tests, set the XDS_CLIENT_SUPPLIER (or inject an XdsClient supplier) before resolving
- Check that no double-shading of io.grpc.xds leaves two copies of the class with separate statics
Example fix
// before XdsNameResolver resolver = new XdsNameResolver(authority, target, ...); // supplier never set // after NameResolverResolverProvider provider = new XdsNameResolverProvider(); NameResolver resolver = provider.newNameResolver(targetUri, args);
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure a supplier is registered before resolving
Supplier<XdsClient> supplier = getXdsClientSupplierOrNull();
if (supplier == null || supplier.get() == null) {
throw new IllegalStateException("XDS_CLIENT_SUPPLIER not initialized");
} Type guard
static boolean isSupplierReady(Supplier<XdsClient> s) {
return s != null && s.get() != null;
} Try / catch
try {
NameResolver nr = provider.newNameResolver(uri, args);
nr.start(watcher);
} catch (XdsInitializationException e) {
log.error("xDS not initialized: {}", e.getMessage());
} Prevention
- Resolve addresses through the standard xDS name resolver provider, not internal classes
- In tests, always install a fake XdsClient supplier before creating resolvers
- Avoid double-shading io.grpc.xds in fat jars
When it happens
Trigger: Constructing/starting XdsNameResolver (or the XdsResolver it delegates to) where the static/injected XDS_CLIENT_SUPPLIER was never set, so getObject() in the pool returns null at XdsNameResolver.java:1121.
Common situations: Unit tests instantiating the resolver without registering a supplier; embedding gRPC xDS internals directly instead of going through nameResolverProvider; classloader/shading issues leaving the static field unset.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Not implemented
- Resolution is pending
- unsupported ExtAuthz service type: only grpc_service is supp
- Invalid ring hash function: " + ringHash.getHashFunction()
- Invalid duration in weighted round robin config: " + ex.getM
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/7a98dbd9478f6fcb.
Report an issue: GitHub.