{"record":{"id":"3b5e49403dc4a480","repo":"grpc/grpc-java","slug":"tls-should-be-configured-by-the-servlet-container","errorCode":null,"errorMessage":"TLS should be configured by the servlet container","messagePattern":"TLS should be configured by the servlet container","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"servlet/src/main/java/io/grpc/servlet/ServletServerBuilder.java","lineNumber":183,"sourceCode":"    checkNotNull(streamTracerFactories, \"streamTracerFactories\");\n    this.streamTracerFactories = streamTracerFactories;\n    internalServer = new InternalServerImpl();\n    return internalServer;\n  }\n\n  @Internal\n  @Override\n  protected ServerBuilder<?> delegate() {\n    return serverImplBuilder;\n  }\n\n  /**\n   * Throws {@code UnsupportedOperationException}. TLS should be configured by the servlet\n   * container.\n   */\n  @Override\n  public ServletServerBuilder useTransportSecurity(File certChain, File privateKey) {\n    throw new UnsupportedOperationException(\"TLS should be configured by the servlet container\");\n  }\n\n  /**\n   * Specifies how to determine gRPC method name from servlet request.\n   *\n   * <p>The default strategy is using {@link HttpServletRequest#getRequestURI()} without the leading\n   * slash.</p>\n   */\n  public ServletServerBuilder methodNameResolver(\n      Function<HttpServletRequest, String> methodResolver) {\n    this.methodNameResolver = checkNotNull(methodResolver);\n    return this;\n  }\n\n  @Override\n  public ServletServerBuilder maxInboundMessageSize(int bytes) {\n    checkArgument(bytes >= 0, \"bytes must be >= 0\");\n    maxInboundMessageSize = bytes;","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/servlet/src/main/java/io/grpc/servlet/ServletServerBuilder.java#L165-L201","documentation":"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.","triggerScenarios":"Calling useTransportSecurity(File certChain, File privateKey) on a ServletServerBuilder when attempting to configure certificates the way one would with NettyServerBuilder.","commonSituations":"Porting server code from NettyServerBuilder to ServletServerBuilder and copying over TLS configuration lines; expecting the builder API to be uniform across transports.","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"],"exampleFix":"// before\nserverBuilder.useTransportSecurity(new File(\"cert.pem\"), new File(\"key.pem\")); // throws\n// after\n// configure TLS in web.xml / container config; no code needed in ServletServerBuilder","handlingStrategy":"fallback","validationCode":"if (builder instanceof ServletServerBuilder) { /* configure TLS in servlet container instead */ }","typeGuard":null,"tryCatchPattern":"try { builder.useTransportSecurity(cert, key); } catch (UnsupportedOperationException e) { log.info(\"Configure TLS in the servlet container\"); }","preventionTips":["Never copy NettyServerBuilder TLS config to servlet builders","Terminate TLS at the servlet container or reverse proxy","Document transport-specific builder capabilities"],"tags":["grpc","servlet","tls","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}