denoland/deno · error · DOMException

SyntaxError

Error message

SyntaxError

What it means

The EventSource constructor resolves its first argument against the current location with the URL parser. If parsing fails, the URL constructor's message is wrapped into a DOMException named 'SyntaxError'. This happens before any connection is attempted, so it is purely an invalid-URL error, not a network error.

Source

Thrown at ext/fetch/27_eventsource.js:212

  #headers;

  constructor(url, eventSourceInitDict = { __proto__: null }) {
    super();
    this[webidl.brand] = webidl.brand;
    const prefix = "Failed to construct 'EventSource'";
    webidl.requiredArguments(arguments.length, 1, prefix);
    url = webidl.converters.USVString(url, prefix, "Argument 1");
    eventSourceInitDict = webidl.converters.EventSourceInit(
      eventSourceInitDict,
      prefix,
      "Argument 2",
    );

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

    this.#url = url;
    this.#withCredentials = eventSourceInitDict.withCredentials;
    this.#headers = eventSourceInitDict.headers;

    this.#loop();
  }

  close() {
    webidl.assertBranded(this, EventSourcePrototype);
    this.#abortController.abort();
    this.#readyState = CLOSED;
    if (this.#reconnectionTimerId) core.cancelTimer(this.#reconnectionTimerId);
  }

  async #loop() {
    const lastEventIdValue = this.#lastEventId;

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Pass a fully-qualified absolute URL: new EventSource("https://example.com/events")
  2. Build the URL first with new URL(path, base) and pass .href so failures surface at the construction site
  3. encodeURIComponent() every dynamic segment that may contain spaces or non-ASCII characters

Example fix

// before
const es = new EventSource(`/events?room=${roomName}`); // SyntaxError for names with spaces

// after
const es = new EventSource(`/events?room=${encodeURIComponent(roomName)}`);
Defensive patterns

Strategy: validation

Validate before calling

function toAbsoluteEventSourceUrl(input, base) {
  try {
    return new URL(input, base).href; // throws on invalid input
  } catch {
    throw new Error(`invalid EventSource URL: ${JSON.stringify(input)}`);
  }
}
const es = new EventSource(toAbsoluteEventSourceUrl(path, location.href));

Type guard

function isParsableUrl(input: string, base?: string): boolean {
  try {
    new URL(input, base);
    return true;
  } catch {
    return false;
  }
}

Try / catch

let es;
try {
  es = new EventSource(url);
} catch (err) {
  if (err instanceof DOMException && err.name === "SyntaxError") {
    // fix the URL string; this is not a network failure
    throw new Error(`bad EventSource URL: ${url}`);
  }
  throw err;
}

Prevention

When it happens

Trigger: new EventSource("not a url"), URLs with unencoded spaces or invalid percent-encoding, or a relative URL when there is no usable base location for the worker.

Common situations: Passing a bare path like "/events" where no document base exists; forgetting encodeURIComponent on dynamic path segments; copy-pasting a URL with quotes or whitespace; constructing URLs from user input unvalidated.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/e5410646c664da01. Report an issue: GitHub.