withastro/astro · error · AstroError

ForbiddenRewrite

ForbiddenRewrite

Error message

You tried to rewrite the on-demand route '${from}' with the static route '${to}', when using the 'server' output. 

The static route '${to}' is rendered by the component
'${component}', which is marked as prerendered. This is a forbidden operation because during the build, the component '${component}' is compiled to an
HTML file, which can't be retrieved at runtime by Astro.

What it means

AstroErrorData.ForbiddenRewrite is thrown when a rewrite targets a prerendered route from an on-demand (SSR) route while the manifest is server-like. During build, prerendered routes compile to plain HTML files and disappear from the server manifest, so the running server has no component to render for them — the rewrite is impossible by construction, not merely unsupported.

Solutions

  1. Remove `export const prerender = true` from the target route so it stays renderable on demand
  2. Redirect instead of rewriting: return Astro.redirect(target) — static HTML files are still served, so the URL change is safe
  3. If the target must stay prerendered, link to it or fetch its content server-side instead of rewriting

Example fix

// before
return Astro.rewrite('/prerendered-page');

// after
return Astro.redirect('/prerendered-page');
Defensive patterns

Strategy: try-catch

Try / catch

import { AstroError } from 'astro/errors';
try {
  return await Astro.rewrite(target);
} catch (err) {
  if (err instanceof AstroError && err.code === 'ForbiddenRewrite') {
    // target is prerendered — redirect instead; the static file is still served
    return Astro.redirect(target);
  }
  throw err;
}

Prevention

When it happens

Trigger: Astro.rewrite('/prerendered-page') or next('/prerendered-page') from an SSR route, when the target has `export const prerender = true` and the project builds with output 'server'.

Common situations: Marking marketing/docs pages prerendered for performance while app pages rewrite into them; migrating a site from static to server output where old rewrites now point at pages that became static; shared routing tables that mix both kinds of routes.

Understand the failure class

Related errors


AI-assisted analysis of withastro/astro@157c500c38 (2026-08-18). Data as JSON: /api/errors/75bedbbf4cc93b0d. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/core/middleware/sequence.ts:78

						} else {
							const request =
								handleContext.request.method === 'GET' || handleContext.request.method === 'HEAD'
									? handleContext.request
									: handleContext.request.clone();
							const newUrl =
								payload instanceof URL ? payload : new URL(payload, handleContext.url.origin);
							newRequest = copyRequest(newUrl, request, false, state.logger, routeData.route);
						}

						// This is a case where the user tries to rewrite from a SSR route to a prerendered route (SSG).
						// This case isn't valid because when building for SSR, the prerendered route disappears from the server output because it becomes an HTML file,
						// so Astro can't retrieve it from the emitted manifest.
						if (
							manifest.serverLike === true &&
							handleContext.isPrerendered === false &&
							routeData.prerender === true
						) {
							throw new AstroError({
								...ForbiddenRewrite,
								message: ForbiddenRewrite.message(
									handleContext.url.pathname,
									pathname,
									routeData.component,
								),
								hint: ForbiddenRewrite.hint(routeData.component),
							});
						}

						carriedPayload = payload;
						handleContext.request = newRequest;
						handleContext.url = new URL(newRequest.url);
						handleContext.params = getParams(routeData, pathname);
						handleContext.routePattern = routeData.route;
						setOriginPathname(
							handleContext.request,
							oldPathname,

View on GitHub (pinned to 157c500c38)