{"record":{"id":"92ab986f3ae91da7","repo":"eclipse-vertx/vert.x","slug":"pqc-enforcement-policy-pqcpolicy-requires-pq-co","errorCode":null,"errorMessage":"PQC enforcement policy ${pqcPolicy} requires PQ compliant named groups but the configured SSL engine does not support it","messagePattern":"PQC enforcement policy (.+?) requires PQ compliant named groups but the configured SSL engine does not support it","errorType":"exception","errorClass":"VertxException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/internal/tls/SslContextManager.java","lineNumber":99,"sourceCode":"  /**\n   * Resolve the ssl engine options to use for properly running the configured options,\n   * taking PQC enforcement policy into account.\n   */\n  public static SSLEngineOptions resolveEngineOptions(SSLEngineOptions engineOptions, boolean useAlpn, PqcEnforcementPolicy pqcPolicy) {\n    if (pqcPolicy == null) {\n      pqcPolicy = PqcEnforcementPolicy.RELAXED;\n    }\n    if (pqcPolicy == PqcEnforcementPolicy.STRICT || pqcPolicy == PqcEnforcementPolicy.CLIENT_NEGOTIATED) {\n      if (engineOptions != null) {\n        // we check that the user provided a PQ compliant SSL Engine\n        boolean pqcSupported;\n        if (engineOptions instanceof JdkSSLEngineOptions) {\n          pqcSupported = JdkSSLEngineOptions.isPqcAvailable();\n        } else {\n          pqcSupported = OpenSSLEngineOptions.isPqcAvailable();\n        }\n        if (!pqcSupported) {\n          throw new VertxException(\"PQC enforcement policy \" + pqcPolicy + \" requires PQ compliant named groups but the configured SSL engine does not support it\");\n        }\n      } else {\n        // the user didn't specify any SSL engine, we pick one for them\n        if (JdkSSLEngineOptions.isPqcAvailable()) {\n          log.debug(\"JdkSslEngine supports PQ compliant groups, it will be used for the application\");\n          engineOptions = new JdkSSLEngineOptions();\n        } else if (OpenSSLEngineOptions.isPqcAvailable()) {\n          log.debug(\"OpenSslEngine supports PQ compliant groups, it will be used for the application\");\n          engineOptions = new OpenSSLEngineOptions();\n        } else {\n          throw new VertxException(\"PQC enforcement policy \" + pqcPolicy + \" requires PQ compliant named groups but neither JDK nor OpenSSL support it\");\n        }\n      }\n    }\n    if (engineOptions == null) {\n      if (useAlpn) {\n        if (JdkSSLEngineOptions.isAlpnAvailable()) {\n          engineOptions = new JdkSSLEngineOptions();","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/internal/tls/SslContextManager.java#L81-L117","documentation":"SslContextManager.resolveEngineOptions throws VertxException when a PQC enforcement policy is configured but the explicitly chosen SSL engine (JDK or OpenSSL as set by the user) does not expose PQ-compliant named groups (e.g. ML-KEM hybrids). Vert.x refuses to run with a policy it cannot satisfy.","triggerScenarios":"Setting sslEngineOptions to JdkSSLEngineOptions or OpenSSLEngineOptions while requiring a PQC enforcement policy, and JdkSSLEngineOptions.isPqcAvailable()/OpenSSLEngineOptions.isPqcAvailable() returns false (old JDK or OpenSSL without PQ groups).","commonSituations":"Running on JDK < 24 (or without hybrid X25519MLKEM768 groups) or a netty-tcnative build without PQ support while a security policy mandates post-quantum key exchange.","solutions":["Upgrade to a JDK/OpenSSL that supports PQ named groups (e.g. JDK 24+, OpenSSL 3.5+ with ML-KEM).","Remove the explicit sslEngineOptions so Vert.x auto-selects a PQ-capable engine.","Lower/relax the PQC enforcement policy if PQ groups are not actually required.","For OpenSSL, use a netty-tcnative BoringSSL build with PQ groups enabled."],"exampleFix":"// before\noptions.setSslEngineOptions(new JdkSSLEngineOptions()); // JDK without PQ\n// after\n// omit engine options: Vert.x picks a PQ-capable engine\noptions.setPqcPolicy(PqcPolicy.ENFORCE);","handlingStrategy":"validation","validationCode":"if (!JdkSSLEngineOptions.isPqcAvailable() && !OpenSSLEngineOptions.isPqcAvailable()) {\n  throw new IllegalStateException(\"Runtime does not support PQ named groups; do not force an engine with PQC policy\");\n}","typeGuard":null,"tryCatchPattern":"try { engineOpts = manager.resolveEngineOptions(...); } catch (VertxException e) { /* fall back to non-enforced policy or abort with clear message */ }","preventionTips":["Call JdkSSLEngineOptions.isPqcAvailable()/OpenSSLEngineOptions.isPqcAvailable() at boot before enabling a PQC policy","Avoid pinning JdkSSLEngineOptions/OpenSSLEngineOptions when PQC enforcement is on","Keep JDK and netty-tcnative up to date in CI images"],"tags":["ssl","pqc","post-quantum","tls"],"backgroundTag":"unsupported-config-value","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}