grpc/grpc-java · error · IllegalStateException
NameResolverRegistry is not set in Builder
Error message
NameResolverRegistry is not set in Builder
What it means
NameResolver.Args.Builder.getNameResolverRegistry() throws IllegalStateException when nameResolverRegistry was never set via setNameResolverRegistry(). The registry (experimental since 1.74.0) lets a NameResolver look up nested providers to create child resolvers. Accessing it on Args built without it is an invariant violation: gRPC always sets this field when constructing Args internally, so null indicates the Args came from incomplete custom code.
Source
Thrown at api/src/main/java/io/grpc/NameResolver.java:525
return overrideAuthority;
}
/**
* Returns the {@link MetricRecorder} that the channel uses to record metrics.
*/
public MetricRecorder getMetricRecorder() {
return metricRecorder;
}
/**
* Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
* NameResolver}s.
*
* @since 1.74.0
*/
public NameResolverRegistry getNameResolverRegistry() {
if (nameResolverRegistry == null) {
throw new IllegalStateException("NameResolverRegistry is not set in Builder");
}
return nameResolverRegistry;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("defaultPort", defaultPort)
.add("proxyDetector", proxyDetector)
.add("syncContext", syncContext)
.add("serviceConfigParser", serviceConfigParser)
.add("customArgs", customArgs)
.add("scheduledExecutorService", scheduledExecutorService)
.add("channelLogger", channelLogger)
.add("executor", executor)
.add("overrideAuthority", overrideAuthority)
.add("metricRecorder", metricRecorder)
.add("nameResolverRegistry", nameResolverRegistry)View on GitHub (pinned to 64daddc1f3)
Solutions
- Add setNameResolverRegistry(NameResolverRegistry.getDefaultRegistry()) or the channel-provided registry on the Args.Builder before build()
- If you don't need the registry, avoid calling getNameResolverRegistry() on hand-built Args and pass dependencies explicitly to your resolver constructor instead
- Check for gRPC version skew: ensure the component constructing NameResolver.Args is on a version >= 1.74.0 that populates the registry field
Example fix
// before
NameResolver.Args args = new NameResolver.Args.Builder()
.setUri(uri)
.build();
NameResolverRegistry registry = args.getNameResolverRegistry(); // throws
// after
NameResolver.Args args = new NameResolver.Args.Builder()
.setUri(uri)
.setNameResolverRegistry(NameResolverRegistry.getDefaultRegistry())
.build();
NameResolverRegistry registry = args.getNameResolverRegistry(); Defensive patterns
Strategy: validation
Validate before calling
// before consuming Args
NameResolverRegistry registry;
try {
registry = args.getNameResolverRegistry();
} catch (IllegalStateException e) {
registry = NameResolverRegistry.getDefaultRegistry();
} Type guard
boolean hasRegistry(NameResolver.Args args) {
try { return args.getNameResolverRegistry() != null; }
catch (IllegalStateException e) { return false; }
} Try / catch
try {
registry = args.getNameResolverRegistry();
} catch (IllegalStateException e) {
registry = NameResolverRegistry.getDefaultRegistry();
} Prevention
- Set setNameResolverRegistry(NameResolverRegistry.getDefaultRegistry()) on any hand-built Args.Builder
- Keep all gRPC artifacts on the same version so Args-producing code populates the 1.74.0+ field
- Prefer taking resolver dependencies via constructor injection rather than reading optional Args fields
When it happens
Trigger: Calling getNameResolverRegistry() on NameResolver.Args whose Builder lacked a setNameResolverRegistry(...) call — e.g. inside a custom NameResolverProvider.newNameResolver that reads the registry, while the Args were assembled by test code or an older builder invocation that predates the 1.74.0 field.
Common situations: Custom NameResolver implementations that delegate to child resolvers via the registry; unit tests building Args manually; mixing gRPC versions where an integration layer (e.g. grpc-xds or a third-party resolver) builds Args without the registry field set.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- ChannelLogger is not set in Builder
- No ALTS context information found
- Can't set TLS settings for ALTS
- Not implemented
- Not implemented
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/583709e0f435355e.
Report an issue: GitHub.