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
ForbiddenRewrite: in 'server' output, Astro.rewrite() tried to route an on-demand (SSR) request to a prerendered route. Prerendered routes compile to static HTML at build time and are not present in the server manifest, so they cannot be served at runtime — the rewrite is forbidden (i18n fallback routes excepted).
Source
Thrown at packages/astro/src/core/rewrites/handler.ts:53
state: FetchState,
payload: RewritePayload,
{ routeData, componentInstance, newUrl, pathname }: TryRewriteResult,
{ mergeCookies = false }: { mergeCookies?: boolean } = {},
): void {
const pipeline = state.pipeline;
const oldPathname = state.pathname;
// Disallow SSR→prerender rewrites: the prerendered route becomes a
// static HTML file during build and isn't available in the server
// manifest. Allow i18n fallback routes as an exception.
const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0;
if (
pipeline.manifest.serverLike &&
!state.routeData!.prerender &&
routeData.prerender &&
!isI18nFallback
) {
throw new AstroError({
...ForbiddenRewrite,
message: ForbiddenRewrite.message(state.pathname, pathname, routeData.component),
hint: ForbiddenRewrite.hint(routeData.component),
});
}
state.routeData = routeData;
state.componentInstance = componentInstance;
if (payload instanceof Request) {
state.request = payload;
} else {
state.request = copyRequest(
newUrl,
state.request,
routeData.prerender,
pipeline.logger,
state.routeData!.route,
);View on GitHub (pinned to d081033d5f)
Solutions
- Add `export const prerender = false` to the destination component so it renders on demand.
- Use Astro.redirect() instead of Astro.rewrite() when the target must stay static (a real navigation, not an internal rewrite).
- Re-check whether the destination route is in the SSR server manifest.
Example fix
// before — destination pages/about.astro is prerendered
Astro.rewrite('/about');
// after — make the destination on-demand
// pages/about.astro
export const prerender = false; Defensive patterns
Strategy: validation
Validate before calling
function canRewriteTo(fromPrerender: boolean, toPrerender: boolean, serverLike: boolean, isI18nFallback: boolean): boolean {
if (serverLike && !fromPrerender && toPrerender && !isI18nFallback) return false;
return true;
}
// before Astro.rewrite, ensure the destination is on-demand Try / catch
try {
Astro.rewrite(target);
} catch (e) {
if (e instanceof AstroError && e.code === 'ForbiddenRewrite') {
return Astro.redirect(target); // fall back to a real navigation
}
throw e;
} Prevention
- Mark rewrite destinations with `export const prerender = false`.
- Prefer Astro.redirect() when the target must remain static.
- Document which routes are on-demand vs prerendered in an i18n or routing map.
When it happens
Trigger: Calling Astro.rewrite('/static-page') from an SSR route where /static-page is prerendered; a prerendered destination route while output is 'server'; middleware rewriting on-demand requests to prerendered pages.
Common situations: Migrating pages between prerendered and on-demand; using Astro.rewrite to route to a page intended to be static; forgetting that output:'server' still prerenders pages without `export const prerender = false` being absent (i.e. the target defaulted to prerender).
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- ForbiddenRewrite
- PrerenderClientAddressNotAvailable
- NoMatchingStaticPathFound
- PrerenderDynamicEndpointPathCollide
- MissingIndexForInternationalizationError
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/a5621a3b97dd6fcc.
Report an issue: GitHub.