{"record":{"id":"44068e537a3973e5","repo":"grpc/grpc-java","slug":"resolution-is-pending","errorCode":null,"errorMessage":"Resolution is pending","messagePattern":"Resolution is pending","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/grpc/internal/ManagedChannelImpl.java","lineNumber":153,"sourceCode":"  @VisibleForTesting\n  static final Status SHUTDOWN_NOW_STATUS =\n      Status.UNAVAILABLE.withDescription(\"Channel shutdownNow invoked\");\n\n  @VisibleForTesting\n  static final Status SHUTDOWN_STATUS =\n      Status.UNAVAILABLE.withDescription(\"Channel shutdown invoked\");\n\n  @VisibleForTesting\n  static final Status SUBCHANNEL_SHUTDOWN_STATUS =\n      Status.UNAVAILABLE.withDescription(\"Subchannel shutdown invoked\");\n\n  private static final ManagedChannelServiceConfig EMPTY_SERVICE_CONFIG =\n      ManagedChannelServiceConfig.empty();\n  private static final InternalConfigSelector INITIAL_PENDING_SELECTOR =\n      new InternalConfigSelector() {\n        @Override\n        public Result selectConfig(PickSubchannelArgs args) {\n          throw new IllegalStateException(\"Resolution is pending\");\n        }\n      };\n  private static final LoadBalancer.PickDetailsConsumer NOOP_PICK_DETAILS_CONSUMER =\n      new LoadBalancer.PickDetailsConsumer() {};\n\n  /**\n   * Retrieves the user-provided configuration function for internal child channels.\n   *\n   * <p>This is intended for use by gRPC internal components\n   * that are responsible for creating auxiliary {@code ManagedChannel} instances.\n   */\n  private final ChannelConfigurator channelConfigurator;\n\n  private final InternalLogId logId;\n  private final String target;\n  @Nullable\n  private final String authorityOverride;\n  private final NameResolverRegistry nameResolverRegistry;","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java#L135-L171","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nConfigSelector cs = channel.getConfigSelector();\nResult r = cs.selectConfig(args); // may throw\n// after\nchannel.getState(true); // trigger resolution\n// use ConfigSelector only from LoadBalancer callbacks after resolution completes","handlingStrategy":"try-catch","validationCode":"// Guard: only use config selection after channel state leaves IDLE/connecting\nboolean ready = channel.getState(false) == io.grpc.ConnectivityState.READY;","typeGuard":"InternalConfigSelector sel = channel.getConfigSelector();\nif (sel == null) return null; // not yet resolved","tryCatchPattern":"try {\n  return selector.selectConfig(args);\n} catch (IllegalStateException e) {\n  if (\"Resolution is pending\".equals(e.getMessage())) return defaultConfig(args);\n  throw e;\n}","preventionTips":["Never read the config selector synchronously right after channel creation.","Drive config-dependent logic from LoadBalancer/NameResolver callbacks.","Await ConnectivityState.READY before config lookups."],"tags":["grpc","channel-state","race-condition","internal"],"backgroundTag":"invalid-state-transition","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}