grpc/grpc-java · error · UnsupportedOperationException
TLS should be configured by the servlet container
Error message
TLS should be configured by the servlet container
What it means
ServletServerBuilder.useTransportSecurity is intentionally unsupported: in the servlet gRPC transport, TLS termination happens in the servlet container (e.g. Tomcat, Jetty), not in the gRPC server builder. Calling this method always throws UnsupportedOperationException to make that explicit.
Solutions
- Remove the useTransportSecurity call and configure HTTPS/TLS on the servlet container instead
- Deploy the servlet behind a TLS-terminating reverse proxy (nginx, load balancer) and keep the servlet endpoint plain HTTP
- Revert to a transport like NettyServerBuilder if in-process TLS configuration is required
Example fix
// before
serverBuilder.useTransportSecurity(new File("cert.pem"), new File("key.pem")); // throws
// after
// configure TLS in web.xml / container config; no code needed in ServletServerBuilder Defensive patterns
Strategy: fallback
Validate before calling
if (builder instanceof ServletServerBuilder) { /* configure TLS in servlet container instead */ } Try / catch
try { builder.useTransportSecurity(cert, key); } catch (UnsupportedOperationException e) { log.info("Configure TLS in the servlet container"); } Prevention
- Never copy NettyServerBuilder TLS config to servlet builders
- Terminate TLS at the servlet container or reverse proxy
- Document transport-specific builder capabilities
When it happens
Trigger: Calling useTransportSecurity(File certChain, File privateKey) on a ServletServerBuilder when attempting to configure certificates the way one would with NettyServerBuilder.
Common situations: Porting server code from NettyServerBuilder to ServletServerBuilder and copying over TLS configuration lines; expecting the builder API to be uniform across transports.
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.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Can't set TLS settings for ALTS
- decrypt is not supported.
- Not enough information to validate peer. SSLEngine or…
- This method is deprecated and marked for removal. Use the…
- TLS not supported in BinderServer
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/3b5e49403dc4a480.
Report an issue: GitHub.
Appendix: source
Thrown at servlet/src/main/java/io/grpc/servlet/ServletServerBuilder.java:183
checkNotNull(streamTracerFactories, "streamTracerFactories");
this.streamTracerFactories = streamTracerFactories;
internalServer = new InternalServerImpl();
return internalServer;
}
@Internal
@Override
protected ServerBuilder<?> delegate() {
return serverImplBuilder;
}
/**
* Throws {@code UnsupportedOperationException}. TLS should be configured by the servlet
* container.
*/
@Override
public ServletServerBuilder useTransportSecurity(File certChain, File privateKey) {
throw new UnsupportedOperationException("TLS should be configured by the servlet container");
}
/**
* Specifies how to determine gRPC method name from servlet request.
*
* <p>The default strategy is using {@link HttpServletRequest#getRequestURI()} without the leading
* slash.</p>
*/
public ServletServerBuilder methodNameResolver(
Function<HttpServletRequest, String> methodResolver) {
this.methodNameResolver = checkNotNull(methodResolver);
return this;
}
@Override
public ServletServerBuilder maxInboundMessageSize(int bytes) {
checkArgument(bytes >= 0, "bytes must be >= 0");
maxInboundMessageSize = bytes;View on GitHub (pinned to 64daddc1f3)