denoland/deno · error · TypeError

ERR_INVALID_URL

ERR_INVALID_URL

Error message

Invalid URL: ${urlStr}

What it means

getURLOrigin parses a string with new URL(urlStr) and takes .origin; any parse failure is rethrown as ERR_INVALID_URL. It is used when submitting ORIGIN frames (http2session.origin(...origins)), alt-svc frames (http2session.altsvc(alt, origin)), and when computing session.originSet, so HTTP/2 metadata frames never carry a malformed origin.

Source

Thrown at ext/node/polyfills/http2.ts:307

}

function debugSession(sessionType, message, ...args) {
  ReflectApply(debug, null, [
    "Http2Session %s: " + message,
    sessionName(sessionType),
    ...new SafeArrayIterator(args),
  ]);
}

function debugSessionObj(session, message, ...args) {
  debugSession(session[kType], message, ...new SafeArrayIterator(args));
}

function getURLOrigin(urlStr) {
  try {
    return new URL(urlStr).origin;
  } catch {
    throw new ERR_INVALID_URL(urlStr);
  }
}

function perfNow() {
  return webPerformance.now();
}

function emitSessionPerfEntry(session) {
  if (session[kPerfEmitted]) return;
  session[kPerfEmitted] = true;
  const stats = session[kPerfStats];
  if (!stats) return;

  const startTime = stats.startTime;
  const duration = perfNow() - startTime;
  const handle = session[kHandle];
  const framesReceived = handle && typeof handle.framesReceived === "function"
    ? handle.framesReceived()

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass full absolute URLs with scheme and host: session.origin('https://example.com:8443')
  2. Pass URL objects instead of strings — the implementation uses their .origin property and skips parsing
  3. Pre-validate with new URL(str) (or URL.canParse(str)) before calling origin() or altsvc()

Example fix

// before
session.origin('example.com'); // throws ERR_INVALID_URL

// after
session.origin(new URL('https://example.com')); // uses .origin, no parse risk
Defensive patterns

Strategy: validation

Validate before calling

const parseableOrigin = (s: string): boolean => {
  try {
    return new URL(s).origin !== 'null';
  } catch {
    return false;
  }
};
if (!parseableOrigin(originStr)) throw new Error(`bad origin: ${originStr}`);
session.origin(originStr);

Type guard

const isAbsoluteHttpUrl = (v: string): boolean =>
  URL.canParse(v) && /^https?:$/.test(new URL(v).protocol);

Try / catch

try {
  session.origin(originStr);
} catch (err) {
  if ((err as NodeJS.ErrnoException).code === 'ERR_INVALID_URL') {
    // drop or fix the malformed origin, then continue
  } else throw err;
}

Prevention

When it happens

Trigger: session.origin('example.com') (no scheme); session.altsvc('h2=":8443"', 'https://') (empty host); origins built by concatenation that yield strings with spaces or invalid characters; passing a URL string that is not absolute (no protocol).

Common situations: Config files that store bare hostnames and are fed to session.origin/altsvc without normalization; building origins from user input via template strings; non-ASCII or unserialized punycode hostnames; porting code that assumed lenient parsing.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/8fc1e5702654b114. Report an issue: GitHub.