grpc/grpc-java · error · UnsupportedOperationException

Not implemented

Error message

Not implemented

What it means

ClientStreamTracer.Factory.newClientStreamTracer() is a convenience default whose base implementation deliberately throws UnsupportedOperationException; subclasses are expected to override it. Calling the factory without an override produces this error.

Source

Thrown at api/src/main/java/io/grpc/ClientStreamTracer.java:157

  }

  /**
   * Factory class for {@link ClientStreamTracer}.
   */
  public abstract static class Factory {
    /**
     * Creates a {@link ClientStreamTracer} for a new client stream.  This is called inside the
     * transport when it's creating the stream.
     *
     * @param info information about the stream
     * @param headers the mutable headers of the stream. It can be safely mutated within this
     *        method.  Changes made to it will be sent by the stream.  It should not be saved
     *        because it is not safe for read or write after the method returns.
     *
     * @since 1.20.0
     */
    public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
      throw new UnsupportedOperationException("Not implemented");
    }
  }

  /**
   * Information about a stream.
   *
   * <p>Note this class doesn't override {@code equals()} and {@code hashCode}, as is the case for
   * {@link CallOptions}.
   *
   * @since 1.20.0
   */
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2861")
  public static final class StreamInfo {
    private final CallOptions callOptions;
    private final int previousAttempts;
    private final boolean isTransparentRetry;
    private final boolean isHedging;

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Override newClientStreamTracer(StreamInfo info, Metadata headers) in your Factory subclass and return a real ClientStreamTracer
  2. If no tracing is needed, return a no-op ClientStreamTracer instead of relying on the default
  3. In tests, use or extend a no-op/fake tracer factory rather than instantiating ClientStreamTracer.Factory directly

Example fix

// before
ClientStreamTracer.Factory factory = new ClientStreamTracer.Factory() {};
// after
ClientStreamTracer.Factory factory = new ClientStreamTracer.Factory() {
  @Override
  public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata headers) {
    return new ClientStreamTracer() {}; // no-op tracer
  }
};
Defensive patterns

Strategy: try-catch

Try / catch

try {
  ClientStreamTracer tracer = factory.newClientStreamTracer(info, headers);
} catch (UnsupportedOperationException e) {
  tracer = new ClientStreamTracer() {}; // no-op fallback
}

Prevention

When it happens

Trigger: Using a ClientStreamTracer.Factory (or anonymous subclass) that does not override newClientStreamTracer(StreamInfo, Metadata), then letting gRPC create a stream — e.g. via CallOptions.withStreamTracerFactory(...) with an empty factory body, or framework/test helpers (newSubstream, maxConcurrentRequests LB tests) that invoke the factory directly.

Common situations: Copy-pasted factory stubs left unimplemented; anonymous Factory instances created only to satisfy an API; upgrading gRPC where instrumentation code assumed a different factory hook; tests exercising tracers (singlePolicyTypicalWorkflow, childTracer) against a factory that was never completed.

Related errors


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