grpc/grpc-java · error · UnsupportedOperationException

Not implemented

Error message

Not implemented

What it means

ManagedChannel.getState(boolean) is an ExperimentalApi base method that throws UnsupportedOperationException unless the concrete channel implementation overrides it. It reports the channel's ConnectivityState, optionally requesting a connection. The stub exists so implementations lacking connectivity tracking can simply inherit rather than fake a state.

Source

Thrown at api/src/main/java/io/grpc/ManagedChannel.java:85

   *
   * @return whether the channel is terminated, as would be done by {@link #isTerminated()}.
   * @since 1.0.0
   */
  public abstract boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

  /**
   * Gets the current connectivity state. Note the result may soon become outdated.
   *
   * <p>Note that the core library did not provide an implementation of this method until v1.6.1.
   *
   * @param requestConnection if {@code true}, the channel will try to make a connection if it is
   *        currently IDLE
   * @throws UnsupportedOperationException if not supported by implementation
   * @since 1.1.0
   */
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4359")
  public ConnectivityState getState(boolean requestConnection) {
    throw new UnsupportedOperationException("Not implemented");
  }

  /**
   * Registers a one-off callback that will be run if the connectivity state of the channel diverges
   * from the given {@code source}, which is typically what has just been returned by {@link
   * #getState}.  If the states are already different, the callback will be called immediately.  The
   * callback is run in the same executor that runs Call listeners.
   *
   * <p>There is an inherent race between the notification to {@code callback} and any call to
   * {@code getState()}. There is a similar race between {@code getState()} and a call to {@code
   * notifyWhenStateChanged()}. The state can change during those races, so there is not a way to
   * see every state transition. "Transitions" to the same state are possible, because intermediate
   * states may not have been observed. The API is only reliable in tracking the <em>current</em>
   * state.
   *
   * <p>Note that the core library did not provide an implementation of this method until v1.6.1.
   *
   * @param source the assumed current state, typically just returned by {@link #getState}

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Use a standard channel implementation (NettyChannelBuilder/OkHttpChannelBuilder/InProcessChannelBuilder) that overrides getState
  2. Guard with a capability check and handle the absence of state tracking instead of polling getState
  3. Catch UnsupportedOperationException and treat the channel as state-unknown, relying on RPC failures instead
  4. If you implement ManagedChannel yourself, override getState(boolean) and notifyWhenStateChanged to keep them consistent

Example fix

// before
ConnectivityState s = channel.getState(false); // may throw
// after
ConnectivityState s;
try {
  s = channel.getState(false);
} catch (UnsupportedOperationException e) {
  s = ConnectivityState.IDLE; // implementation does not expose state
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: assume state support on known implementations
boolean supportsState = !(channel instanceof my.TestChannel); // or check concrete type before polling

Type guard

boolean supportsConnectivityState(ManagedChannel ch) {
  return ch.getClass().getName().startsWith("io.grpc.") && !(ch instanceof my.TestChannel);
}

Try / catch

try {
  state = channel.getState(false);
} catch (UnsupportedOperationException e) {
  state = null; // connectivity state not tracked by this implementation
}

Prevention

When it happens

Trigger: Calling channel.getState(requestConnection) on a ManagedChannel implementation that has not overridden getState — observed in tests like childChannelConfigurator_passedToResolvingOobChannelNameResolverArgs, oobChannelHasNoChannelCallCredentials, oobChannelWithOobChannelCredsHasChannelCallCredentials, and assertRpcFails, which call it on channels built from builders whose impl does not support it.

Common situations: Using a minimal/custom ManagedChannel (e.g., a test double or a wrapper built via ManagedChannelBuilder with limited features); xDS out-of-band channels in configurations where the underlying builder does not implement connectivity-state APIs; older or third-party transports predating the 1.1.0 connectivity API.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/353f541684da95f5. Report an issue: GitHub.