grpc/grpc-java · error · IllegalStateException
ChannelLogger is not set in Builder
Error message
ChannelLogger is not set in Builder
What it means
NameResolver.Args.Builder.getChannelLogger() throws IllegalStateException when channelLogger was never set via setChannelLogger(). The ChannelLogger is an experimental API component (since 1.26.0) that NameResolver implementations use to emit channel-level trace logs. gRPC requires it to be provided before the Args object is consumed, so reading it in an unset state is treated as a programming/invariant error rather than a recoverable failure.
Source
Thrown at api/src/main/java/io/grpc/NameResolver.java:471
*
* <p>Custom args can also be used simply to avoid adding inappropriate deps to the low level
* io.grpc package.
*/
@SuppressWarnings("unchecked") // Cast is safe because all put()s go through the setArg() API.
@Nullable
public <T> T getArg(Key<T> key) {
return customArgs != null ? (T) customArgs.get(key) : null;
}
/**
* Returns the {@link ChannelLogger} for the Channel served by this NameResolver.
*
* @since 1.26.0
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/6438")
public ChannelLogger getChannelLogger() {
if (channelLogger == null) {
throw new IllegalStateException("ChannelLogger is not set in Builder");
}
return channelLogger;
}
/**
* Returns the configurator for child channels.
*
* @since 1.83.0
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/12574")
public ChannelConfigurator getChildChannelConfigurator() {
return channelConfigurator;
}
/**
* Returns the Executor on which this resolver should execute long-running or I/O bound work.
* Null if no Executor was set.
*View on GitHub (pinned to 64daddc1f3)
Solutions
- Call setChannelLogger(...) on the Args.Builder before building, e.g. with args.getChannelLogger() passed in from the channel, or a Noop/Testing logger in tests
- Guard the call: use args.getChannelLogger() only inside a NameResolver whose Args were supplied by grpc's ManagedChannel (which always sets it); for hand-built Args in tests, substitute a simple ChannelLogger implementation
- If the Args come from your own provider code, audit the builder call chain and add the missing setChannelLogger call
Example fix
// before
NameResolver.Args args = new NameResolver.Args.Builder()
.setUri(uri)
.setAttributes(attributes)
.build();
ChannelLogger logger = args.getChannelLogger(); // throws IllegalStateException
// after
NameResolver.Args args = new NameResolver.Args.Builder()
.setUri(uri)
.setAttributes(attributes)
.setChannelLogger(channelLogger)
.build();
ChannelLogger logger = args.getChannelLogger(); Defensive patterns
Strategy: validation
Validate before calling
// before consuming Args
if (args.getChannelLoggerOrNull() == null) { // or track your own builder flag
throw new IllegalArgumentException("NameResolver.Args built without setChannelLogger");
}
ChannelLogger logger = args.getChannelLogger(); Type guard
boolean hasChannelLogger(NameResolver.Args args) {
try { return args.getChannelLogger() != null; }
catch (IllegalStateException e) { return false; }
} Try / catch
try {
logger = args.getChannelLogger();
} catch (IllegalStateException e) {
logger = new NoopChannelLogger(); // fall back in tests/custom builders
} Prevention
- Always build NameResolver.Args through the full setX chain including setChannelLogger
- In unit tests, use a Noop/Recording ChannelLogger implementation instead of leaving the field null
- When upgrading gRPC, review NameResolver.Args.Builder for newly added required fields
When it happens
Trigger: Calling getChannelLogger() on a NameResolver.Args instance built by a Builder on which setChannelLogger() was never called — typically a custom NameResolver implementation reading Args inside its factory (newNameResolver) or when the Args were constructed by non-gRPC code that omitted the field.
Common situations: Implementing a custom NameResolver/NameResolverProvider and calling args.getChannelLogger() while testing with a hand-built Args.Builder that only sets the fields you know about; upgrading gRPC where a previously optional Args field became required for your code path; unit tests that construct NameResolver.Args directly instead of receiving them from the channel.
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
- NameResolverRegistry 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/1507e84cb5ff8794.
Report an issue: GitHub.