denoland/deno · error · DOMException
SyntaxError
SyntaxError
Error message
Failed to parse URL: ${scriptUrl} What it means
importScripts parses each argument with `new URL(scriptUrl, baseUrl)` against the worker's location; a parse failure throws DOMException(`Failed to parse URL: ${scriptUrl}`, 'SyntaxError') in runtime/js/99_main.js. The check is purely syntactic — it validates that the argument is an absolute URL or resolvable relative URL per the WHATWG parser; reachability is only tested later by op_worker_sync_fetch.
Source
Thrown at runtime/js/99_main.js:400
op_worker_maybe_wait_for_debugger();
dispatchWorkerMessage(syncData);
}
}
}
let loadedMainWorkerScript = false;
function importScripts(...urls) {
if (op_worker_get_type() !== "classic") {
throw new TypeError("Cannot import scripts in a module worker");
}
const baseUrl = location.getLocationHref();
const parsedUrls = ArrayPrototypeMap(urls, (scriptUrl) => {
try {
return new url.URL(scriptUrl, baseUrl ?? undefined).href;
} catch {
throw new DOMException(
`Failed to parse URL: ${scriptUrl}`,
"SyntaxError",
);
}
});
// A classic worker's main script has looser MIME type checks than any
// imported scripts, so we use `loadedMainWorkerScript` to distinguish them.
// TODO(andreubotella) Refactor worker creation so the main script isn't
// loaded with `importScripts()`.
const scripts = op_worker_sync_fetch(
parsedUrls,
!loadedMainWorkerScript,
);
loadedMainWorkerScript = true;
for (let i = 0; i < scripts.length; ++i) {
const { url, script } = scripts[i];View on GitHub (pinned to a961cdec3b)
Solutions
- Pass a well-formed absolute or resolvable-relative URL, percent-encoded where needed
- Pre-validate with `URL.canParse(scriptUrl, baseUrl)` (or a try/catch around new URL) before calling importScripts
- Build URLs programmatically with `new URL(path, base).href` and pass the result
Example fix
// before
importScripts(base + '?file=' + fileName + '&mode=' + mode);
// after
importScripts(
new URL(
`?file=${encodeURIComponent(fileName)}&mode=${encodeURIComponent(mode)}`,
base,
).href,
); Defensive patterns
Strategy: validation
Validate before calling
const base = typeof location !== 'undefined' ? location.href : undefined;
if (!URL.canParse(scriptUrl, base)) {
throw new Error(`importScripts argument is not a parseable URL: ${scriptUrl}`);
}
importScripts(scriptUrl); Try / catch
try {
importScripts(u);
} catch (e) {
if (e instanceof DOMException && e.name === 'SyntaxError') {
// fix the URL string (encode components) and retry
} else {
throw e;
}
} Prevention
- Percent-encode dynamic query components with encodeURIComponent
- Build URLs with new URL(...) instead of string concatenation
- Pre-check user/config-derived URLs with URL.canParse before passing them to importScripts
When it happens
Trigger: `importScripts('not a url ::')`; strings with unencoded spaces or query fragments; Windows paths like 'C:\lib.js'; a relative URL when the worker has no base href (baseUrl null).
Common situations: Building script URLs by string concatenation without encodeURIComponent; passing file paths from configuration; porting scripts that relied on eval-style path resolution.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Request url protocol must be 'http:' or 'https:': received '
- ERR_INVALID_URL
- Invalid URL: '${href}' with base '${maybeBase}'
- package name contains a URL path or delimiter character
- Cannot import scripts in a module worker
AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20).
Data as JSON: /api/errors/2186320054f79dbe.
Report an issue: GitHub.