grpc/grpc-java · error · UnsupportedOperationException
ClientTransportServersBuilder is required, use a constructor
Error message
ClientTransportServersBuilder is required, use a constructor
What it means
ServerImplBuilder is the base class for concrete server builders (e.g. NettyServerBuilder). Its static inherited forPort(int) method cannot construct a transport-agnostic server, so it's annotated @DoNotCall and always throws UnsupportedOperationException, instructing users to use a concrete constructor.
Source
Thrown at core/src/main/java/io/grpc/internal/ServerImplBuilder.java:66
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
* Default builder for {@link io.grpc.Server} instances, for usage in Transport implementations.
*/
public final class ServerImplBuilder extends ServerBuilder<ServerImplBuilder> {
private static final Logger log = Logger.getLogger(ServerImplBuilder.class.getName());
@DoNotCall("ClientTransportServersBuilder is required, use a constructor")
public static ServerBuilder<?> forPort(int port) {
throw new UnsupportedOperationException(
"ClientTransportServersBuilder is required, use a constructor");
}
// defaults
private static final ObjectPool<? extends Executor> DEFAULT_EXECUTOR_POOL =
SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
private static final HandlerRegistry DEFAULT_FALLBACK_REGISTRY = new DefaultFallbackRegistry();
private static final DecompressorRegistry DEFAULT_DECOMPRESSOR_REGISTRY =
DecompressorRegistry.getDefaultInstance();
private static final CompressorRegistry DEFAULT_COMPRESSOR_REGISTRY =
CompressorRegistry.getDefaultInstance();
private static final long DEFAULT_HANDSHAKE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(120);
// mutable state
final InternalHandlerRegistry.Builder registryBuilder =
new InternalHandlerRegistry.Builder();
final List<ServerTransportFilter> transportFilters = new ArrayList<>();
final List<ServerInterceptor> interceptors = new ArrayList<>();View on GitHub (pinned to 64daddc1f3)
Solutions
- Use a concrete transport builder: NettyServerBuilder.forPort(port) or NettyServerBuilder.forPort with grpc-netty dependency
- Add the transport dependency (grpc-netty or grpc-netty-shaded) so ServerBuilder.forPort can find a provider via META-INF/services
- Replace generic ServerBuilder.forPort calls in framework code with the transport-specific constructor
Example fix
// before Server server = ServerBuilder.forPort(8080).build(); // no transport provider // after Server server = NettyServerBuilder.forPort(8080).build();
Defensive patterns
Strategy: type-guard
Validate before calling
if (b instanceof ServerImplBuilder) { throw new IllegalStateException("No transport provider; add grpc-netty and use NettyServerBuilder"); } Type guard
static boolean hasTransportProvider(ServerBuilder<?> b) { return !(b instanceof io.grpc.internal.ServerImplBuilder); } Try / catch
try { server = ServerBuilder.forPort(port).build(); } catch (UnsupportedOperationException e) { if (e.getMessage().contains("ClientTransportServersBuilder is required")) { server = NettyServerBuilder.forPort(port).build(); } else throw e; } Prevention
- Always construct servers with a concrete builder (NettyServerBuilder)
- Ensure a transport artifact (grpc-netty/-shaded) is on the runtime classpath
- Don't rely on ServerBuilder.forPort service-loading in shaded environments
When it happens
Trigger: Calling ServerBuilder.forPort(port) generically (e.g. via reflection or generic code paths) when the resolved builder is ServerImplBuilder rather than a concrete transport builder like NettyServerBuilder.forPort().
Common situations: Using ServerBuilder.forPort() without grpc-netty(-shaded) on the classpath so the service loader finds no provider and falls back to ServerImplBuilder; generic framework code calling ServerBuilder.forPort directly.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- TLS not supported in ServerImplBuilder
- Can't set TLS settings for ALTS
- OkHttpChannelBuilder not found on the classpath
- Unsupported operation getPort()
- Not implemented
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/323bfeb7343b39ee.
Report an issue: GitHub.