grpc/grpc-java · error · UnsupportedOperationException

Not implemented

Error message

Not implemented

What it means

This is a placeholder method inside CallCredentials.RequestInfo: the default RequestInfo supplied by the library does not carry a CallOptions, so getCallOptions() deliberately throws UnsupportedOperationException. Only RequestInfo instances created by a real transport provide actual call options.

Source

Thrown at api/src/main/java/io/grpc/CallCredentials.java:99

     * Called when there has been an error when preparing the headers. This will fail the RPC.
     */
    public abstract void fail(Status status);
  }

  /**
   * The request-related information passed to {@code CallCredentials.applyRequestMetadata()}.
   */
  public abstract static class RequestInfo {
    /**
     * The method descriptor of this RPC.
     */
    public abstract MethodDescriptor<?, ?> getMethodDescriptor();

    /**
     * The call options used to call this RPC.
     */
    public CallOptions getCallOptions() {
      throw new UnsupportedOperationException("Not implemented");
    }

    /**
     * The security level on the transport.
     */
    public abstract SecurityLevel getSecurityLevel();

    /**
     * Returns the authority string used to authenticate the server for this call.
     */
    public abstract String getAuthority();

    /**
     * Returns the transport attributes.
     */
    @Grpc.TransportAttr
    public abstract Attributes getTransportAttrs();
  }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Do not rely on getCallOptions() in credentials logic; capture needed options elsewhere (e.g. pass them into your CallCredentials at construction)
  2. In tests, provide a RequestInfo subclass/anonymous implementation that overrides getCallOptions() to return the desired CallOptions
  3. Guard usage: only call getCallOptions() when the RequestInfo originated from an actual transport

Example fix

// before
String authority = requestInfo.getCallOptions().getAuthority();
// after
private final String authority; // captured when credentials were constructed
public void applyRequestMetadata(RequestInfo info, Executor appExecutor, MetadataApplier applier) {
  // use this.authority instead of info.getCallOptions()
}
Defensive patterns

Strategy: type-guard

Type guard

boolean hasCallOptions(CallCredentials.RequestInfo info) {
  try { info.getCallOptions(); return true; }
  catch (UnsupportedOperationException e) { return false; }
}

Try / catch

try {
  CallOptions opts = requestInfo.getCallOptions();
  // use opts
} catch (UnsupportedOperationException e) {
  // RequestInfo is not transport-backed; fall back to options captured at construction time
}

Prevention

When it happens

Trigger: Implementing a custom CallCredentials and calling requestInfo.getCallOptions() inside applyRequestMetadata when the RequestInfo was not supplied by a real gRPC transport (e.g. a hand-constructed RequestInfo, a mock, or the default returned by CallCredentials.RequestInfo's anonymous implementation).

Common situations: Unit tests of custom credential implementations that construct fake RequestInfo objects; code paths that copy the default RequestInfo; framework code (like the parameterPropagation test helper) invoking the method outside a real transport context.

Related errors


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