sveltejs/kit · error
DEV: Cannot use `${caller}` with an external URL. Use `windo
Error message
DEV: Cannot use `${caller}` with an external URL. Use `window.location = "${url}"` instead | PROD: ${caller}: invalid URL What it means
resolve_intent() validates that every client-side navigation target is a same-origin URL that resolves to a route in the app. External origins are disallowed because SvelteKit's client router cannot manage a full page load to another origin. In production the message is minified to `${caller}: invalid URL` to keep bundles small.
Source
Thrown at packages/kit/src/runtime/client/client.js:2643
if (updating || !started) {
autoscroll = false;
}
}
let warned_on_invalidate_all = false;
let warned_on_replace_state = false;
let warned_on_push_state = false;
let warned_on_replace_state_function = false;
/**
* @param {string | URL} url
* @param {'goto' | 'pushState' | 'replaceState'} caller
*/
async function resolve_intent(url, caller) {
const resolved = new URL(resolve_url(url));
if (resolved.origin !== origin) {
throw new Error(
DEV
? `Cannot use \`${caller}\` with an external URL. Use \`window.location = "${url}"\` instead`
: `${caller}: invalid URL`
);
}
const intent = await get_navigation_intent(resolved, false);
if (!intent) {
throw new Error(
DEV
? `Cannot use \`${caller}\` with a URL that does not resolve to a route within the app. Use \`window.location = "${url}"\` instead`
: `${caller}: invalid URL`
);
}
return intent;
}View on GitHub (pinned to 03f1687fe6)
Solutions
- Use window.location = url (or window.location.href = url) for external URLs
- Verify the URL origin matches window.location.origin before calling goto/pushState/replaceState
- Fix svelte.config.js paths.base / paths.assets so internal links resolve same-origin
- In production, decode the short message: `${caller}: invalid URL` means an external or unroutable URL was passed
Example fix
// before
await goto('https://example.com/checkout');
// after
window.location.href = 'https://example.com/checkout'; Defensive patterns
Strategy: validation
Validate before calling
function isInternalUrl(url) {
const u = new URL(url, location.href);
return u.origin === location.origin;
}
// call goto only if isInternalUrl(target) Type guard
function isSameOrigin(u) { try { return new URL(u, location.href).origin === location.origin; } catch { return false; } } Try / catch
try { await goto(url); } catch (e) { if (String(e.message).includes('invalid URL') || e.message.includes('external URL')) { window.location.href = url; } else { throw e; } } Prevention
- Check origin equality before any programmatic navigation
- Use window.location for all off-site redirects
- Audit svelte.config.js paths when deploying under a base path
When it happens
Trigger: Calling goto('https://other-site.com'), pushState()/replaceState() with a URL whose origin differs from `origin`, or a base-relative URL that resolves to an external origin (e.g. wrong `paths.base` config producing an absolute external URL).
Common situations: Redirecting to an OAuth provider or payment gateway via goto(); concatenating API base URLs into goto(); misconfigured svelte.config.js paths or PRerendered absolute links; code migrated from an app that used location.href-style strings.
Related errors
- DEV: Cannot use `${caller}` with a URL that does not resolve
- Files prefixed with + are reserved (saw ${project_relative})
- Only Svelte files can reference named layouts. Remove '${mat
- Files and directories prefixed with + are reserved (saw ${pr
- Invalid route ID ${id}
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/366c9e7da52b3328.
Report an issue: GitHub.