{"record":{"id":"39b3fb4a6b476e19","repo":"eclipse-vertx/vert.x","slug":"http-1-x-connections-don-t-support-settings","errorCode":null,"errorMessage":"HTTP/1.x connections don't support SETTINGS","messagePattern":"HTTP/1\\.x connections don't support SETTINGS","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1Connection.java","lineNumber":117,"sourceCode":"\n  @Override\n  public Http1Connection exceptionHandler(Handler<Throwable> handler) {\n    return (Http1Connection) super.exceptionHandler(handler);\n  }\n\n  @Override\n  public HttpConnection goAway(long errorCode, int lastStreamId, Buffer debugData) {\n    throw new UnsupportedOperationException(\"HTTP/1.x connections don't support GOAWAY\");\n  }\n\n  @Override\n  public HttpConnection goAwayHandler(@Nullable Handler<GoAway> handler) {\n    throw new UnsupportedOperationException(\"HTTP/1.x connections don't support GOAWAY\");\n  }\n\n  @Override\n  public Http2Settings settings() {\n    throw new UnsupportedOperationException(\"HTTP/1.x connections don't support SETTINGS\");\n  }\n\n  @Override\n  public Future<Void> updateSettings(HttpSettings settings) {\n    throw new UnsupportedOperationException(\"HTTP/1.x connections don't support SETTINGS\");\n  }\n\n  @Override\n  public Http2Settings remoteSettings() {\n    throw new UnsupportedOperationException(\"HTTP/1.x connections don't support SETTINGS\");\n  }\n\n  @Override\n  public HttpConnection remoteSettingsHandler(Handler<HttpSettings> handler) {\n    throw new UnsupportedOperationException(\"HTTP/1.x connections don't support SETTINGS\");\n  }\n\n  @Override","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1Connection.java#L99-L135","documentation":"This UnsupportedOperationException is thrown by Http1Connection.settings() because HTTP/1.x has no concept of HTTP/2 SETTINGS frames. The library's HttpConnection interface exposes HTTP/2-only operations, and the HTTP/1.x implementation deliberately rejects them instead of returning null or silently no-oping. It signals a programming error: code is calling HTTP/2-specific API surface on an HTTP/1.x connection.","triggerScenarios":"Calling HttpConnection.settings() on a connection obtained from an HttpClientRequest/HttpClientResponse or HttpServerRequest whose protocol is HTTP/1.0 or HTTP/1.1. Typically code written for HTTP/2 (e.g. after upgrading to h2c or TLS+ALPN) is run against a plain HTTP/1.1 server or client connection.","commonSituations":"An app configured for HTTP/2 in production but connecting over plain TCP without h2c upgrade or ALPN negotiation, so it silently falls back to HTTP/1.1 and later hits HTTP/2-only tuning code (flow-control/limits via SETTINGS). Also generic connection-level middleware that calls settings() unconditionally, and tests running against HTTP/1.x while production uses h2.","solutions":["Check the negotiated protocol before calling HTTP/2-only APIs: only invoke settings() when the request/endpoint is HTTP/2 (e.g. request.version() == HTTP_2 or SSLSession/ALPN shows h2).","Configure the client/server to actually negotiate HTTP/2 (useTLS with ALPN h2, or h2c handling) if you intend to use SETTINGS-based tuning.","If HTTP/1.x is the intended protocol, remove the settings()/updateSettings() calls and tune HTTP/1.x behavior via its own options (e.g. keep-alive, pipelining, max concurrent streams equivalents in HttpClientOptions).","Wrap the call defensively: catch UnsupportedOperationException and fall back to HTTP/1.x-compatible behavior instead of crashing.","Route HTTP/2-specific logic through a version check rather than assuming the HttpConnection implementation type; or use instanceof / class name checks against Http1Connection in internal code."],"exampleFix":"// before\nHttpConnection conn = request.connection();\nHttp2Settings s = conn.settings(); // throws on HTTP/1.x\n\n// after\nHttpConnection conn = request.connection();\nHttp2Settings s = null;\ntry {\n  s = conn.settings();\n} catch (UnsupportedOperationException e) {\n  // HTTP/1.x connection: SETTINGS not applicable, use defaults\n}","handlingStrategy":"try-catch","validationCode":"boolean http2 = request.version() == HttpVersion.HTTP_2;\nif (!http2) { /* skip settings() call, use HTTP/1.x defaults */ }","typeGuard":"static boolean isHttp2(HttpConnection c) {\n  return !(c instanceof io.vertx.core.http.impl.http1.Http1Connection);\n}","tryCatchPattern":"try {\n  Http2Settings s = conn.settings();\n  apply(s);\n} catch (UnsupportedOperationException e) {\n  // HTTP/1.x: no SETTINGS support, keep defaults\n}","preventionTips":["Check request.version() (or ALPN result) before calling HTTP/2-only HttpConnection methods.","Keep HTTP/2 tuning code in a separate path guarded by protocol checks.","Catch UnsupportedOperationException once in a shared helper that wraps all HTTP/2-only connection calls.","Verify h2 negotiation (ALPN/h2c) in integration tests if settings tuning is part of the flow."],"tags":["http","http2","http1","unsupported-operation","vertx-core"],"backgroundTag":"unsupported-operation","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"}