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
- Override newClientStreamTracer(StreamInfo info, Metadata headers) in your Factory subclass and return a real ClientStreamTracer
- If no tracing is needed, return a no-op ClientStreamTracer instead of relying on the default
- 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
- Always override newClientStreamTracer when subclassing ClientStreamTracer.Factory
- Add a unit test that invokes factory.newClientStreamTracer with a minimal StreamInfo/Metadata
- Prefer returning a no-op tracer over relying on default (throwing) implementations
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
- Can't set TLS settings for ALTS
- Unsupported operation getPort()
- Not implemented
- Subclass failed to hide static factory
- Subclass failed to hide static factory
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/b2b155c2e055e3ee.
Report an issue: GitHub.