{"record":{"id":"0aa33fd3e2660d21","repo":"grpc/grpc-java","slug":"subclass-failed-to-hide-static-factory-0aa33f","errorCode":null,"errorMessage":"Subclass failed to hide static factory","messagePattern":"Subclass failed to hide static factory","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/grpc/ForwardingServerBuilder.java","lineNumber":43,"sourceCode":"import javax.annotation.Nullable;\n\n/**\n * A {@link ServerBuilder} that delegates all its builder methods to another builder by default.\n *\n * @param <T> The type of the subclass extending this abstract class.\n * @since 1.34.0\n */\npublic abstract class ForwardingServerBuilder<T extends ServerBuilder<T>> extends ServerBuilder<T> {\n\n  /** The default constructor. */\n  protected ForwardingServerBuilder() {}\n\n  /**\n   * This method serves to force sub classes to \"hide\" this static factory.\n   */\n  @DoNotCall(\"Unsupported\")\n  public static ServerBuilder<?> forPort(int port) {\n    throw new UnsupportedOperationException(\"Subclass failed to hide static factory\");\n  }\n\n  /**\n   * Returns the delegated {@code ServerBuilder}.\n   */\n  protected abstract ServerBuilder<?> delegate();\n\n  @Override\n  public T directExecutor() {\n    delegate().directExecutor();\n    return thisT();\n  }\n\n  @Override\n  public T executor(@Nullable Executor executor) {\n    delegate().executor(executor);\n    return thisT();\n  }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/api/src/main/java/io/grpc/ForwardingServerBuilder.java#L25-L61","documentation":"ForwardingServerBuilder is an abstract delegating wrapper around ServerBuilder. Its static forPort() is marked @DoNotCall and exists only to force subclasses to hide it with their own forPort(); calling the base implementation always throws UnsupportedOperationException since the wrapper cannot construct a concrete server builder.","triggerScenarios":"Calling ForwardingServerBuilder.forPort(port) directly, or through a forwarding subclass that failed to declare its own static forPort(int). Also triggered by reflection or generic server-bootstrap code that resolves forPort on the base wrapper class.","commonSituations":"Generic server startup code reading a builder class name from configuration and invoking forPort on it when that class is (or extends) ForwardingServerBuilder; custom forwarding server builders missing the shadowing static method; IDE auto-import selecting the base class.","solutions":["Call the concrete builder's static factory, e.g. MyServerBuilder.forPort(9090), never ForwardingServerBuilder.forPort","If you maintain a forwarding subclass, add your own static forPort(int) that builds via your delegate()","For reflection-based bootstrap, resolve forPort on the concrete subclass Class, not the base wrapper"],"exampleFix":"// before\nServerBuilder<?> b = ForwardingServerBuilder.forPort(9090);\n// after\nServerBuilder<?> b = MyServerBuilder.forPort(9090); // subclass's own static factory","handlingStrategy":"validation","validationCode":"// Ensure the concrete subclass shadows forPort before server bootstrap\nif (MyServerBuilder.class.getMethod(\"forPort\", int.class).getDeclaringClass()\n    == io.grpc.ForwardingServerBuilder.class) {\n  throw new IllegalStateException(\"Subclass must shadow forPort\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  serverBuilder = MyServerBuilder.forPort(port);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"Subclass failed to hide static factory\")) {\n    serverBuilder = ServerBuilder.forPort(port);\n  } else throw e;\n}","preventionTips":["Call forPort on your concrete server builder class only","When subclassing ForwardingServerBuilder, add your own static forPort immediately","In config-driven bootstrap, verify the configured builder class actually declares its own static factories"],"tags":["unsupported-operation","static-factory","forwarding-builder","server"],"backgroundTag":"unsupported-operation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}