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
- Pass a fully-qualified absolute URL: new EventSource("https://example.com/events")
- Build the URL first with new URL(path, base) and pass .href so failures surface at the construction site
- 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
- Always pass an absolute URL to EventSource
- Build URLs with new URL(path, base).href so parsing errors surface early with context
- encodeURIComponent all dynamic query/segment values
- Distinguish DOMException SyntaxError (bad URL) from later connection errors when reporting
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
- Request url protocol must be 'http:' or 'https:': received '
- Blob URL fetch only supports GET method
- ERR_INVALID_URL
- Scope '{}' was not a directory path.
- Unable to construct URL from the path of cwd: {}
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/e5410646c664da01.
Report an issue: GitHub.