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
Thrown during a rewrite inside sequenced middleware when an on-demand (SSR) route tries to rewrite to a prerendered (SSG) route while output is 'server'. Prerendered routes are emitted as static HTML files at build time and are not in the server manifest, so the runtime cannot render them on demand. The check requires serverLike === true, the source isPrerendered === false, and the target routeData.prerender === true.
Source
Thrown at packages/astro/src/core/middleware/sequence.ts:66
handleContext.request.clone(),
);
}
const oldPathname = handleContext.url.pathname;
const pipeline: Pipeline = Reflect.get(handleContext, pipelineSymbol);
const { routeData, pathname } = await pipeline.tryRewrite(
payload,
handleContext.request,
);
// 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 (
pipeline.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 d081033d5f)
Solutions
- Make the target route server-rendered (remove `export const prerender = true`) so it exists in the server manifest.
- Use a redirect (HTTP) to the static HTML file instead of an in-rewrite, if the static route must stay prerendered.
- Reorganize routes so SSR-to-prerendered rewrites are unnecessary.
Example fix
// before - target page has prerender = true, source is SSR
return context.next('/static-page'); // ForbiddenRewrite
// after - remove prerender from target, or use a redirect
return context.redirect('/static-page'); Defensive patterns
Strategy: validation
Validate before calling
// Verify target route is server-rendered before rewriting.
const pipeline = Reflect.get(context, pipelineSymbol);
const { routeData } = await pipeline.tryRewrite(target, context.request);
if (pipeline.manifest.serverLike && routeData.prerender) {
// use redirect instead of rewrite
return context.redirect(target);
}
return context.next(target); Type guard
function isRewritableTarget(routeData: { prerender?: boolean }, serverLike: boolean): boolean {
return !(serverLike && routeData.prerender === true);
} Try / catch
try {
return await context.next('/some-route');
} catch (e) {
if (e instanceof Error && /forbidden operation/i.test(e.message)) {
return context.redirect('/some-route'); // static HTML exists
}
throw e;
} Prevention
- Do not rewrite from SSR routes to prerendered routes; redirect instead.
- Audit prerender flags when using rewrites across route types.
- Keep dynamic redirect maps aware of prerender status.
When it happens
Trigger: Calling next(rewritePayload) (or returning a rewrite) from an SSR page/middleware to a route that has `export const prerender = true`, in a project with output 'server'. The ForbiddenRewrite error names the from-URL, the to-URL, and the target component.
Common situations: Mixing prerendered and on-demand routes and using rewrites to navigate between them; marking a route prerender=true but linking to it dynamically; refactoring routing without considering prerender status.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- ForbiddenRewrite
- PrerenderClientAddressNotAvailable
- RewriteWithBodyUsed
- MiddlewareNotAResponse
- MiddlewareNoDataOrNextCalled
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/75bedbbf4cc93b0d.
Report an issue: GitHub.