grpc/grpc-java · error · IllegalStateException
Resolution is pending
Error message
Resolution is pending
What it means
ManagedChannelImpl installs INITIAL_PENDING_SELECTOR as a placeholder InternalConfigSelector before the first resolution completes. If any code attempts to select a service config via this placeholder before resolution finishes, it throws IllegalStateException("Resolution is pending") — this selector is only expected to be consulted when channel state bookkeeping is wrong.
Source
Thrown at core/src/main/java/io/grpc/internal/ManagedChannelImpl.java:153
@VisibleForTesting
static final Status SHUTDOWN_NOW_STATUS =
Status.UNAVAILABLE.withDescription("Channel shutdownNow invoked");
@VisibleForTesting
static final Status SHUTDOWN_STATUS =
Status.UNAVAILABLE.withDescription("Channel shutdown invoked");
@VisibleForTesting
static final Status SUBCHANNEL_SHUTDOWN_STATUS =
Status.UNAVAILABLE.withDescription("Subchannel shutdown invoked");
private static final ManagedChannelServiceConfig EMPTY_SERVICE_CONFIG =
ManagedChannelServiceConfig.empty();
private static final InternalConfigSelector INITIAL_PENDING_SELECTOR =
new InternalConfigSelector() {
@Override
public Result selectConfig(PickSubchannelArgs args) {
throw new IllegalStateException("Resolution is pending");
}
};
private static final LoadBalancer.PickDetailsConsumer NOOP_PICK_DETAILS_CONSUMER =
new LoadBalancer.PickDetailsConsumer() {};
/**
* Retrieves the user-provided configuration function for internal child channels.
*
* <p>This is intended for use by gRPC internal components
* that are responsible for creating auxiliary {@code ManagedChannel} instances.
*/
private final ChannelConfigurator channelConfigurator;
private final InternalLogId logId;
private final String target;
@Nullable
private final String authorityOverride;
private final NameResolverRegistry nameResolverRegistry;View on GitHub (pinned to 64daddc1f3)
Solutions
- Wait for the channel to become READY (or for onResolved callbacks) before consulting the config selector.
- Register a LoadBalancer/Subchannel listener and only use config selection after resolution state transitions.
- If this occurs in normal operation, file a bug — the placeholder is not meant to be reachable.
Example fix
// before ConfigSelector cs = channel.getConfigSelector(); Result r = cs.selectConfig(args); // may throw // after channel.getState(true); // trigger resolution // use ConfigSelector only from LoadBalancer callbacks after resolution completes
Defensive patterns
Strategy: try-catch
Validate before calling
// Guard: only use config selection after channel state leaves IDLE/connecting boolean ready = channel.getState(false) == io.grpc.ConnectivityState.READY;
Type guard
InternalConfigSelector sel = channel.getConfigSelector(); if (sel == null) return null; // not yet resolved
Try / catch
try {
return selector.selectConfig(args);
} catch (IllegalStateException e) {
if ("Resolution is pending".equals(e.getMessage())) return defaultConfig(args);
throw e;
} Prevention
- Never read the config selector synchronously right after channel creation.
- Drive config-dependent logic from LoadBalancer/NameResolver callbacks.
- Await ConnectivityState.READY before config lookups.
When it happens
Trigger: Calling selectConfig on the channel's InternalConfigSelector while the NameResolver has not yet returned its first result, typically via internal APIs or ConfigSelector usage racing with channel startup.
Common situations: Custom balancers or internal tooling reading the config selector immediately after channel creation, before name resolution completes; race conditions between resolution start and config lookup.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Caller failed to initialize XDS_CLIENT_SUPPLIER
- No ALTS context information found
- Can't set TLS settings for ALTS
- Counter has overflowed.
- Invalid frame length ${dataLength}
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/44068e537a3973e5.
Report an issue: GitHub.