denoland/deno · error · TypeError
ERR_HTTP2_ALTSVC_INVALID_ORIGIN
ERR_HTTP2_ALTSVC_INVALID_ORIGIN
Error message
HTTP/2 ALTSVC frames require a valid origin
What it means
In altsvc(alt, originOrStream), when originOrStream is a string it is parsed with getURLOrigin(), which returns new URL(str).origin. URLs that have an opaque/undefined origin (origin === "null" — e.g. file:, data:, or other non-hierarchical schemes) produce ERR_HTTP2_ALTSVC_INVALID_ORIGIN because an ALTSVC frame needs a concrete serialized origin. Note that a string the URL constructor cannot parse at all throws ERR_INVALID_URL earlier instead.
Source
Thrown at ext/node/polyfills/http2.ts:4586
return this[kServer];
}
// Submits an altsvc frame to be sent to the client. `stream` is a
// numeric Stream ID. origin is a URL string that will be used to get
// the origin. alt is a string containing the altsvc details. No fancy
// API is provided for that.
altsvc(alt, originOrStream) {
if (this.destroyed) {
throw new ERR_HTTP2_INVALID_SESSION();
}
let stream = 0;
let origin;
if (typeof originOrStream === "string") {
origin = getURLOrigin(originOrStream);
if (origin === "null") {
throw new ERR_HTTP2_ALTSVC_INVALID_ORIGIN();
}
} else if (typeof originOrStream === "number") {
if (originOrStream >>> 0 !== originOrStream || originOrStream === 0) {
throw new ERR_OUT_OF_RANGE(
"originOrStream",
`> 0 && < ${2 ** 32}`,
originOrStream,
);
}
stream = originOrStream;
} else if (originOrStream !== undefined) {
// Allow origin to be passed a URL or object with origin property
if (originOrStream !== null && typeof originOrStream === "object") {
origin = originOrStream.origin;
}
// Note: if originOrStream is an object with an origin property other
// than a URL, then it is possible that origin will be malformed.
// We do not verify that here. Users who go that route need toView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass an absolute http/https URL such as 'https://example.com:8443' so URL.origin is concrete
- Build the origin from the request's authority: `https://${req.authority}` or `https://${req.headers.host}`
- If you only mean a stream, pass the numeric stream ID instead of a URL
Example fix
// before
session.altsvc('h2=":8443"', new URL(req.url, 'file:///').href); // origin === 'null'
// after
session.altsvc('h2=":8443"', `https://${clientSocket.remoteAddress}`); Defensive patterns
Strategy: validation
Validate before calling
const origin = new URL(urlString).origin;
if (origin === 'null') throw new TypeError(`no usable origin in ${urlString}`);
session.altsvc(alt, urlString); Type guard
function hasConcreteOrigin(urlString) {
try { return new URL(urlString).origin !== 'null'; } catch { return false; }
} Prevention
- Always pass absolute http/https URLs with scheme and host
- Build origins from the request authority/Host header, never from req.url paths
- Remember: unparseable strings throw ERR_INVALID_URL, opaque origins (file:, data:) throw this error
When it happens
Trigger: session.altsvc(alt, 'file:///srv/site'), altsvc(alt, 'data:text/plain,hi'), or any scheme where URL.prototype.origin is the string 'null'.
Common situations: Deriving the origin from req.url (a path like '/foo') instead of the Host header or absolute URL; feeding a config value that lost its scheme ('example.com:8443' is unparseable, 'file://' mounts are 'null'); handling non-HTTP origins in a generic adapter.
Related errors
- ERR_INVALID_URL
- ERR_INVALID_CHAR
- ERR_HTTP2_ALTSVC_LENGTH
- ERR_HTTP2_INVALID_ORIGIN
- ERR_HTTP2_NO_SOCKET_MANIPULATION
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/6e8bcbb7bc1cc2ef.
Report an issue: GitHub.