withastro/astro · error · AstroError

UnsupportedExternalRedirect

UnsupportedExternalRedirect

Error message

The destination URL in the external redirect from "${from}" to "${to}" is unsupported.

What it means

UnsupportedExternalRedirect: a configured redirect's destination is a parseable URL that does not start with http:// or https://. Astro only permits external redirects over HTTP(S); other protocols (ftp://, mailto:, relative, or malformed scheme) are rejected at manifest build time.

Source

Thrown at packages/astro/src/core/routing/create-manifest.ts:542

		const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic)
			? `/${segments.map((segment) => segment[0].content).join('/')}`
			: null;
		const params = segments
			.flat()
			.filter((p) => p.dynamic)
			.map((p) => p.content);
		const route = joinSegments(segments);

		let destination: string;
		if (typeof to === 'string') {
			destination = to;
		} else {
			destination = to.destination;
		}

		// check if the link starts with http or https; if not, throw an error
		if (URL.canParse(destination) && !/^https?:\/\//.test(destination)) {
			throw new AstroError({
				...UnsupportedExternalRedirect,
				message: UnsupportedExternalRedirect.message(from, destination),
			});
		}

		const redirectRoute = routeMap.get(destination);

		// If the source has dynamic params and the redirect will be prerendered,
		// we need a valid redirectRoute to map them. Without it, the build will fail
		// later with a misleading error. Catch this early and provide a clear error message.
		if (
			params.length > 0 &&
			!redirectRoute &&
			!URL.canParse(destination) &&
			getPrerenderDefault(config)
		) {
			throw new AstroError({
				...InvalidRedirectDestination,

View on GitHub (pinned to d081033d5f)

Solutions

  1. Change the destination to start with http:// or https://.
  2. If the destination is a local path, drop the scheme and use a root-relative '/path'.
  3. Validate redirect destinations against /^https?:\/\// before deploying config.

Example fix

// before — astro.config.mjs
redirects: { '/old': 'ftp://files.example.com' }

// after
redirects: { '/old': 'https://files.example.com' }
Defensive patterns

Strategy: validation

Validate before calling

function isSupportedExternalRedirect(dest: string): boolean {
  return !URL.canParse(dest) || /^https?:\/\//.test(dest);
}
// validate redirect destinations in config before build

Type guard

function isHttpUrl(value: string): boolean {
  return /^https?:\/\//.test(value);
}

Prevention

When it happens

Trigger: Setting redirects in astro.config to a destination like 'ftp://example.com', '//example.com', or a protocol-relative URL; using a string that URL.canParse accepts but lacks the http(s) scheme.

Common situations: Copying a non-http URL into config.redirects; protocol-relative URLs from legacy configs; accidentally prefixing with a wrong scheme; data-driven redirect config populated from a CMS.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/82c233b5d40e0849. Report an issue: GitHub.