denoland/deno · error · DOMException

SyntaxError

SyntaxError

Error message

e.message

What it means

The WebSocket constructor parses url with the WHATWG URL parser relative to the current location (getLocationHref()). If parsing fails, the underlying error's message (typically 'Invalid URL') is rethrown wrapped in a DOMException named SyntaxError - so the message text varies with the URL parser's failure reason.

Source

Thrown at ext/websocket/01_websocket.js:283

    this[_sendQueue] = [];
    this[_cancelHandle] = undefined;

    const prefix = "Failed to construct 'WebSocket'";
    webidl.requiredArguments(arguments.length, 1, prefix);
    url = webidl.converters.USVString(url, prefix, "Argument 1");
    initOrProtocols = webidl.converters
      ["WebSocketInit or sequence<DOMString> or DOMString"](
        initOrProtocols,
        prefix,
        "Argument 2",
      );

    let wsURL;

    try {
      wsURL = new URL(url, getLocationHref());
    } catch (e) {
      throw new DOMException(e.message, "SyntaxError");
    }

    if (wsURL.protocol === "http:") {
      wsURL.protocol = "ws:";
    } else if (wsURL.protocol === "https:") {
      wsURL.protocol = "wss:";
    }

    if (wsURL.protocol !== "ws:" && wsURL.protocol !== "wss:") {
      throw new DOMException(
        `Only ws & wss schemes are allowed in a WebSocket URL: received ${wsURL.protocol}`,
        "SyntaxError",
      );
    }

    if (wsURL.hash !== "" || StringPrototypeEndsWith(wsURL.href, "#")) {
      throw new DOMException(
        "Fragments are not allowed in a WebSocket URL",

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass an absolute ws:// or wss:// URL string
  2. Validate first with new URL(url) in your own try/catch so you control the error message and stack
  3. URL-encode dynamic path/query components with encodeURIComponent

Example fix

// before
new WebSocket(`${host}/ws`); // host = 'localhost:8080' - no scheme

// after
new WebSocket(`ws://${host}/ws`);
Defensive patterns

Strategy: validation

Validate before calling

function toWsUrl(raw: string): string {
  const u = new URL(raw); // throws early with your stack, not the constructor's
  if (u.protocol !== 'ws:' && u.protocol !== 'wss:') {
    u.protocol = u.protocol === 'https:' ? 'wss:' : 'ws:';
  }
  return u.href;
}

Type guard

const isAbsoluteWsUrl = (u: string): boolean => /^wss?:\/\//i.test(u);

Try / catch

try {
  ws = new WebSocket(url);
} catch (e) {
  if (e instanceof DOMException && e.name === 'SyntaxError') {
    // malformed URL - log the raw value and fix the builder
  } else throw e;
}

Prevention

When it happens

Trigger: new WebSocket(''), new WebSocket('ws://[bad'), an out-of-range port (ws://host:99999), or a malformed string built from undefined variables such as `ws://${host}/ws` when host is undefined.

Common situations: Forgetting the ws:// scheme, template variables that are undefined/null, unencoded spaces in the URL, empty config values at startup, typos when concatenating parts.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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