eclipse-vertx/vert.x · error

426 Upgrade Required (RFC2817)

Error message

426 Upgrade Required (RFC2817)

What it means

SC_UPGRADE_REQUIRED is an HttpResponseExpectation constant for HTTP 426 (RFC2817). The server requires the client to switch to a different protocol (e.g. HTTP to TLS) via the Upgrade header before retrying the request. Vert.x exposes it for status expectations on HttpClient requests.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/HttpResponseExpectation.java:265

  /**
   * 423 Locked (WebDAV, RFC4918)
   */
  HttpResponseExpectation SC_LOCKED = status(423);

  /**
   * 424 Failed Dependency (WebDAV, RFC4918)
   */
  HttpResponseExpectation SC_FAILED_DEPENDENCY = status(424);

  /**
   * 425 Unordered Collection (WebDAV, RFC3648)
   */
  HttpResponseExpectation SC_UNORDERED_COLLECTION = status(425);

  /**
   * 426 Upgrade Required (RFC2817)
   */
  HttpResponseExpectation SC_UPGRADE_REQUIRED = status(426);

  /**
   * 428 Precondition Required (RFC6585)
   */
  HttpResponseExpectation SC_PRECONDITION_REQUIRED = status(428);

  /**
   * 429 Too Many Requests (RFC6585)
   */
  HttpResponseExpectation SC_TOO_MANY_REQUESTS = status(429);

  /**
   * 431 Request Header Fields Too Large (RFC6585)
   */
  HttpResponseExpectation SC_REQUEST_HEADER_FIELDS_TOO_LARGE = status(431);

  /**
   * Any 5XX server error

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Switch the client request to TLS/HTTPS (RequestOptions setSsl(true), port 443).
  2. Retry with the required Upgrade header and protocols listed in the 426 response.
  3. Update hardcoded http:// URLs to https:// in configuration after server policy changes.
  4. If testing upgrade behavior, keep the expectation; otherwise expect 101 Switching Protocols after a valid upgrade.

Example fix

// before
client.request(new RequestOptions().setHost("api.example.com").setPort(80))
// after
client.request(new RequestOptions().setHost("api.example.com").setPort(443).setSsl(true))
Defensive patterns

Strategy: fallback

Validate before calling

if ("http".equals(requestOptions.getUri().substring(0, 4)) && serverRequiresTls) {
  requestOptions.setSsl(true).setPort(443);
}

Type guard

boolean is426(HttpClientResponse resp) { return resp.statusCode() == 426; }

Try / catch

plainRequest().onFailure(err -> {
  if (isCauseStatus(err, 426)) retryWithUpgradeOrTls();
});

Prevention

When it happens

Trigger: Sending a plain-HTTP request to a server that mandates TLS (responds 426 with an Upgrade header), or any endpoint requiring protocol upgrade before the request is accepted. Appears when .expecting(SC_UPGRADE_REQUIRED) is used to test upgrade behavior or when a non-ssl client hits an SSL-required server.

Common situations: Server hardened to require HTTPS after deprecating plain HTTP; misconfigured client still using http:// for an https-only endpoint; WebSocket endpoints requiring a proper Upgrade handshake.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/1f295cc6ba987681. Report an issue: GitHub.