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

  1. Use window.location = url (or window.location.href = url) for external URLs
  2. Verify the URL origin matches window.location.origin before calling goto/pushState/replaceState
  3. Fix svelte.config.js paths.base / paths.assets so internal links resolve same-origin
  4. 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

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


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/366c9e7da52b3328. Report an issue: GitHub.