What version of astro are you using?
6.3.7 (regression introduced in 6.3.6)
Are you using an SSR adapter? If so, which one?
@astrojs/cloudflare (any SSR adapter reproduces — bug is in core)
What package manager are you using?
pnpm
What operating system are you using?
macOS (irrelevant — issue is in production runtime on any platform)
What browser are you using?
N/A
Describe the Bug
Internal Warning: route cache overwritten. (<pattern>_<component>) fires from core/render/route-cache.ts for every dynamic SSR route on its second and subsequent requests within the same module/isolate, when runtimeMode === 'production'.
The warning is cosmetic — responses are still served correctly with the empty SSR static-paths entry — but it floods production logs.
Volume in production
After upgrading our Cloudflare Worker (single SSR Astro site, @astrojs/cloudflare, 5 dynamic-route components) from 6.3.5 → 6.3.7 we observed:
- ~490 warnings within ~1 hour of the new version going live
- Single warning call site (one log fingerprint), triggered by all 5 dynamic-route components
- Prerendered/static routes do not trigger it — only SSR dynamic routes
- Each warning fires once per second-or-later request per dynamic route per Worker isolate; visitor hitting a prerendered URL produces no warning, visitor hitting a dynamic URL whose route already served once in that isolate produces one warning
Root cause
PR #16776 (released in 6.3.6) added && cached.mod === mod to the fast-path check in callGetStaticPaths:
if (cached?.staticPaths && cached.mod === mod) {
return cached.staticPaths;
}
This change is correct for the HMR scenario it fixed, but the SSR branch a few lines below stores the cache entry without mod:
if (ssr && !route.prerender) {
const entry: GetStaticPathsResultKeyed = Object.assign([], { keyed: new Map() });
routeCache.set(route, { ...cached, staticPaths: entry });
// ^^^^^^^^^^^^^^^^^^^^^^ no `mod` here
return entry;
}
Result: on the next request for the same route, cached.mod === undefined while mod is the imported component module → equality check fails → control falls through into the SSR branch again → routeCache.set() runs a second time → RouteCache.set() sees the existing staticPaths entry and emits the warning.
Fix
Include mod in the SSR-branch cache entry, matching the static branch below:
if (ssr && !route.prerender) {
const entry: GetStaticPathsResultKeyed = Object.assign([], { keyed: new Map() });
- routeCache.set(route, { ...cached, staticPaths: entry });
+ routeCache.set(route, { ...cached, mod, staticPaths: entry });
return entry;
}
Minimal reproduction
// repro.mjs
// setup:
// mkdir astro-repro && cd astro-repro
// npm init -y && npm i astro@6.3.7
// save this file as repro.mjs in that dir
// node repro.mjs
//
// (direct file path bypasses astro's package `exports` field which doesn't expose dist/*)
import { RouteCache, callGetStaticPaths } from './node_modules/astro/dist/core/render/route-cache.js';
const warns = [];
const logger = { warn: (_, m) => warns.push(m), debug() {}, info() {}, error() {} };
const cache = new RouteCache(logger, 'production');
const route = {
route: '/[...slug]',
component: 'src/pages/[...slug].astro',
prerender: false,
pattern: /.*/, segments: [], params: ['slug'],
generate: () => '', type: 'page', isIndex: false,
};
const mod = { default: () => null }; // no getStaticPaths needed for SSR branch
const opts = { mod, route, routeCache: cache, ssr: true, base: '/', trailingSlash: 'ignore' };
await callGetStaticPaths(opts);
await callGetStaticPaths(opts);
await callGetStaticPaths(opts);
console.log('warns:', warns.length); // expected: 0, actual on 6.3.7: 2
Run against astro@6.3.7: prints warns: 2.
Run against astro@6.3.5: prints warns: 0.
Apply the one-line diff above: prints warns: 0.
Verified locally
Patched our astro@6.3.7 install via pnpm patch, the production warning stops firing without affecting cache HIT/MISS behaviour or response correctness.
Link to Minimal Reproducible Example
(repro snippet above is fully self-contained)
What version of
astroare you using?6.3.7 (regression introduced in 6.3.6)
Are you using an SSR adapter? If so, which one?
@astrojs/cloudflare(any SSR adapter reproduces — bug is in core)What package manager are you using?
pnpm
What operating system are you using?
macOS (irrelevant — issue is in production runtime on any platform)
What browser are you using?
N/A
Describe the Bug
Internal Warning: route cache overwritten. (<pattern>_<component>)fires fromcore/render/route-cache.tsfor every dynamic SSR route on its second and subsequent requests within the same module/isolate, whenruntimeMode === 'production'.The warning is cosmetic — responses are still served correctly with the empty SSR static-paths entry — but it floods production logs.
Volume in production
After upgrading our Cloudflare Worker (single SSR Astro site,
@astrojs/cloudflare, 5 dynamic-route components) from 6.3.5 → 6.3.7 we observed:Root cause
PR #16776 (released in 6.3.6) added
&& cached.mod === modto the fast-path check incallGetStaticPaths:This change is correct for the HMR scenario it fixed, but the SSR branch a few lines below stores the cache entry without
mod:Result: on the next request for the same route,
cached.mod === undefinedwhilemodis the imported component module → equality check fails → control falls through into the SSR branch again →routeCache.set()runs a second time →RouteCache.set()sees the existingstaticPathsentry and emits the warning.Fix
Include
modin the SSR-branch cache entry, matching the static branch below:if (ssr && !route.prerender) { const entry: GetStaticPathsResultKeyed = Object.assign([], { keyed: new Map() }); - routeCache.set(route, { ...cached, staticPaths: entry }); + routeCache.set(route, { ...cached, mod, staticPaths: entry }); return entry; }Minimal reproduction
Run against
astro@6.3.7: printswarns: 2.Run against
astro@6.3.5: printswarns: 0.Apply the one-line diff above: prints
warns: 0.Verified locally
Patched our
astro@6.3.7install viapnpm patch, the production warning stops firing without affecting cache HIT/MISS behaviour or response correctness.Link to Minimal Reproducible Example
(repro snippet above is fully self-contained)