eclipse-vertx/vert.x · error · IllegalArgumentException
Missing :authority / host header
Error message
Missing :authority / host header
What it means
When opening an HTTP/2 CONNECT stream, DefaultHttp2ClientStream requires the request to have an :authority (host) pseudo-header. For CONNECT requests there is no absolute path to derive the authority from, so it must be set explicitly; otherwise the HTTP/2 frame would be malformed per RFC 7540. Vert.x throws IllegalArgumentException before the stream is created.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/http2/DefaultHttp2ClientStream.java:156
private final boolean end;
private final Promise<Void> promise;
public HeadersWrite(HttpRequestHead request, ByteBuf buf, boolean end, Promise<Void> promise) {
this.request = request;
this.buf = buf;
this.end = end;
this.promise = promise;
}
@Override
public void write() {
HttpRequestHeaders headers = new HttpRequestHeaders(new DefaultHttp2Headers());
headers.method(request.method);
headers.trace(request.traceOperation);
boolean e;
if (request.method == HttpMethod.CONNECT) {
if (request.authority == null) {
throw new IllegalArgumentException("Missing :authority / host header");
}
headers.authority(request.authority);
// don't end stream for CONNECT
e = false;
} else {
headers.path(request.uri);
headers.scheme(connection.isSsl() ? "https" : "http");
if (request.authority != null) {
headers.authority(request.authority);
}
e = end;
}
if (request.headers != null && !request.headers.isEmpty()) {
for (Map.Entry<String, String> header : request.headers) {
CharSequence headerName = HttpUtils.toLowerCase(header.getKey());
if (!AsciiString.contentEquals(TRANSFER_ENCODING, headerName)) {
headers.add(headerName, header.getValue());
}View on GitHub (pinned to fb308bd8c3)
Solutions
- Set the host on RequestOptions: new RequestOptions().setMethod(HttpMethod.CONNECT).setHost("example.com").setPort(443).
- Ensure the authority (host[:port]) string is non-null before sending the request.
- For generic requests, prefer setServer or a full absolute URI so authority is populated.
Example fix
// before
RequestOptions opts = new RequestOptions().setMethod(HttpMethod.CONNECT).setURI("/tunnel");
// after
RequestOptions opts = new RequestOptions()
.setMethod(HttpMethod.CONNECT)
.setHost("upstream.example.com")
.setPort(443); Defensive patterns
Strategy: validation
Validate before calling
if (options.getHost() == null || options.getHost().isEmpty()) throw new IllegalArgumentException("CONNECT requires host"); Try / catch
try { client.request(opts); } catch (IllegalArgumentException e) { if (e.getMessage().contains(":authority")) { opts.setHost(defaultAuthority); client.request(opts); } } Prevention
- Always setHost/setPort for CONNECT requests
- Build a RequestOptions factory that enforces host presence
- Unit-test CONNECT option building
- Prefer absolute URIs so authority is derivable
When it happens
Trigger: Calling HttpClient.request(HttpMethod.CONNECT, ...) or building an HTTP/2 CONNECT request without setting the host/authority on the RequestOptions.
Common situations: Writing a tunnel/proxy client (CONNECT to an upstream host) where the developer passes only a port or omits setHost(); porting HTTP/1.1 CONNECT code that relied on the Host header being synthesized.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- http2MaxPoolSize must be > 0
- Multipart form requires multipart/form-data content type ins
- Sending form requires multipart/form-data or " + HttpHeaders
- Cannot write frame with HTTP/1.x
- A push response cannot promise another push
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/b275721c71d773a1.
Report an issue: GitHub.