Skip to content

Astro 6.3.6+ floods SSR production logs with "Internal Warning: route cache overwritten" (regression from #16776) #16863

@cheets

Description

@cheets

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    - P5: urgentFix build-breaking bugs affecting most users, should be released ASAP (priority)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions