{"record":{"id":"d4c75066176b5f5e","repo":"eclipse-vertx/vert.x","slug":"ssl-configuration-is-necessary-for-a-quic-server","errorCode":null,"errorMessage":"SSL configuration is necessary for a QUIC server","messagePattern":"SSL configuration is necessary for a QUIC server","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/impl/HttpServerBuilderImpl.java","lineNumber":78,"sourceCode":"  }\n\n  public HttpServerBuilderImpl registerWebSocketWriteHandlers(boolean registerWebSocketWriteHandlers) {\n    this.registerWebSocketWriteHandlers = registerWebSocketWriteHandlers;\n    return this;\n  }\n\n  @Override\n  public HttpServerBuilderImpl withConnectHandler(Handler<HttpConnection> handler) {\n    this.connectHandler = handler;\n    return this;\n  }\n\n  @Override\n  public HttpServer build() {\n    boolean useTcp = config.getVersions().contains(HttpVersion.HTTP_1_1) || config.getVersions().contains(HttpVersion.HTTP_2) || config.getVersions().contains(HttpVersion.HTTP_1_0);\n    boolean useQuic = config.getVersions().contains(HttpVersion.HTTP_3);\n    if (useQuic && sslOptions == null) {\n      throw new NullPointerException(\"SSL configuration is necessary for a QUIC server\");\n    }\n    HttpServer server;\n    if (useTcp) {\n      if (useQuic) {\n        HybridHttpServer compositeServer = new HybridHttpServer(vertx, new HttpServerConfig(config), sslOptions.copy(), sslEngineOptions);\n        server = new CleanableHttpServer(vertx, compositeServer);\n      } else {\n        if (sslOptions != null) {\n          sslOptions = sslOptions.copy();\n        }\n        server = new CleanableHttpServer(vertx, new TcpHttpServer(vertx, new HttpServerConfig(config), sslOptions, sslEngineOptions, null, registerWebSocketWriteHandlers));\n      }\n    } else if (useQuic) {\n      server = new CleanableHttpServer(vertx, new QuicHttpServer(vertx, new HttpServerConfig(config), sslOptions.copy(), null));\n    } else {\n      throw new IllegalArgumentException(\"You must set at least one supported HTTP version\");\n    }\n    Handler<HttpConnection> handler = connectHandler;","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/impl/HttpServerBuilderImpl.java#L60-L96","documentation":"HttpServerBuilderImpl.build() throws a NullPointerException when the configured versions include HTTP/3 (QUIC) but no SSL options were set. QUIC mandates TLS 1.3, so a QUIC server cannot be created without an SSL/key-certificate configuration.","triggerScenarios":"Building an HttpServer with .addVersion(HttpVersion.HTTP_3, port) but never calling .setSslOptions(...) on the builder.","commonSituations":"Copy-pasting an HTTP/1.1/2 server config and adding HTTP/3 without key/cert setup; running in environments where key/cert paths are not provisioned (missing env/config).","solutions":["Call setSslOptions(new SslOptions().setKeyCertOptions(...).setTrustOptions(...)) with a valid key/certificate before build()","Remove HTTP_3 from the configured versions if QUIC is not actually needed","Ensure the TLS key/cert configuration is loaded from config/environment and passed to the builder"],"exampleFix":"// before\nHttpServer server =.vertx.createHttpServer()\n  .addVersion(HttpVersion.HTTP_3, 8443)\n  .build(); // throws\n// after\nHttpServer server = vertx.createHttpServer()\n  .addVersion(HttpVersion.HTTP_3, 8443)\n  .setSslOptions(new SslOptions().setKeyCertOptions(new JksOptions().setPath(\"keystore.jks\").setPassword(\"secret\")))\n  .build();","handlingStrategy":"validation","validationCode":"if (versions.contains(HttpVersion.HTTP_3) && sslOptions == null) {\n  throw new IllegalArgumentException(\"HTTP/3 requires setSslOptions(...)\");\n}","typeGuard":"boolean quicReady(HttpServerBuilder b) { return b.sslOptions() != null; } // or track sslOptions yourself before build()","tryCatchPattern":"try {\n  server = builder.build();\n} catch (NullPointerException e) {\n  if (\"SSL configuration is necessary for a QUIC server\".equals(e.getMessage())) {\n    // rebuild without HTTP_3 or with SSL options\n  } else { throw e; }\n}","preventionTips":["Always call setSslOptions when enabling HTTP/3","Provision key/cert paths via config or env before server startup","Validate the version/SSL combination in configuration tests"],"tags":["http3","quic","ssl","server","config"],"backgroundTag":"missing-required-config","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}