Skip to content

[backport]: fix: ensure LRU cache items have minimum size of 1 to prevent unbounded growth#89134

Merged
ztanner merged 1 commit intonext-15-5from
ztanner/backport-89040
Jan 28, 2026
Merged

[backport]: fix: ensure LRU cache items have minimum size of 1 to prevent unbounded growth#89134
ztanner merged 1 commit intonext-15-5from
ztanner/backport-89040

Conversation

@ztanner
Copy link
Member

@ztanner ztanner commented Jan 28, 2026

…ed growth (#89040)

### What?

Prevent LRU cache unbounded growth by requiring `calculateSize` to
return values > 0.

### Why?

When `calculateSize` returned 0 (e.g., for `null` values in the
filesystem route cache), items were never evicted because they didn't
contribute to `totalSize`. This caused unbounded memory growth when
handling dynamic routes like `/api/logs/[id]` where each unique ID
created a new cache entry with size 0.

### How?

1. **LRUCache now throws an error if size ≤ 0** - This catches bugs at
development time rather than silently masking them:
   ```typescript
   if (size <= 0) {
     throw new Error(
\`LRUCache: calculateSize returned ${size}, but size must be > 0. \` +
\`Items with size 0 would never be evicted, causing unbounded cache
growth.\`
     )
   }
   ```

2. **Fixed filesystem.ts** - Null entries (negative cache) now return
size 1 instead of 0:
   ```typescript
   if (!value) {
// Null entries (negative cache) still need a non-zero size for LRU
eviction
     return 1
   }
   ```

3. **Fixed next-dev-server.ts** - Static paths cache now uses `|| 1`
instead of `?? 0`:
   ```typescript
   return JSON.stringify(value.staticPaths)?.length || 1
   ```
@nextjs-bot
Copy link
Collaborator

nextjs-bot commented Jan 28, 2026

Failing test suites

Commit: cae2095 | About building and testing Next.js

pnpm test packages/next-codemod/transforms/__tests__/add-missing-react-import.test.js (job)

  • add-missing-react-import > transforms correctly using "add-missing-react-import/missing-react-import-in-component" data (DD)
Expand output

● add-missing-react-import › transforms correctly using "add-missing-react-import/missing-react-import-in-component" data

expect(received).toEqual(expected) // deep equality

- Expected  - 15
+ Received  + 15

- import React, { Children, isValidElement } from 'react';
-
+ import React, { Children, isValidElement } from 'react';
+ 
- function Heading(props) {
+ function Heading(props) {
-   const { component, className, children, ...rest } = props;
+   const { component, className, children, ...rest } = props;
-   return React.cloneElement(
+   return React.cloneElement(
-     component,
+     component,
-     {
+     {
-       className: [className, component.props.className || ''].join(' '),
+       className: [className, component.props.className || ''].join(' '),
-       ...rest
+       ...rest
-     },
+     },
-     children
+     children
-   );
+   );
- }
-
-
+ }
+ 
+ 
  export default Heading;

  at runInlineTest (../node_modules/.pnpm/jscodeshift@17.0.0_@babel+preset-env@7.26.9_@babel+core@7.26.10_/node_modules/jscodeshift/dist/testUtils.js:49:18)
  at runTest (../node_modules/.pnpm/jscodeshift@17.0.0_@babel+preset-env@7.26.9_@babel+core@7.26.10_/node_modules/jscodeshift/dist/testUtils.js:98:3)
  at Object.<anonymous> (../node_modules/.pnpm/jscodeshift@17.0.0_@babel+preset-env@7.26.9_@babel+core@7.26.10_/node_modules/jscodeshift/dist/testUtils.js:115:7)

pnpm test packages/next-codemod/transforms/__tests__/app-dir-runtime-config-experimental-edge.test.js (job)

  • app-dir-runtime-config-experimental-edge > transforms correctly using "app-dir-runtime-config-experimental-edge/basic" data (DD)
Expand output

● app-dir-runtime-config-experimental-edge › transforms correctly using "app-dir-runtime-config-experimental-edge/basic" data

expect(received).toEqual(expected) // deep equality

- Expected  - 3
+ Received  + 3

- export const runtime = "edge";
+ export const runtime = "edge";
- export default function Page() {
+ export default function Page() {
-   return <div>hello world</div>;
+   return <div>hello world</div>;
  }

  at runInlineTest (../node_modules/.pnpm/jscodeshift@17.0.0_@babel+preset-env@7.26.9_@babel+core@7.26.10_/node_modules/jscodeshift/dist/testUtils.js:49:18)
  at runTest (../node_modules/.pnpm/jscodeshift@17.0.0_@babel+preset-env@7.26.9_@babel+core@7.26.10_/node_modules/jscodeshift/dist/testUtils.js:98:3)
  at Object.<anonymous> (../node_modules/.pnpm/jscodeshift@17.0.0_@babel+preset-env@7.26.9_@babel+core@7.26.10_/node_modules/jscodeshift/dist/testUtils.js:115:7)

@ztanner ztanner marked this pull request as ready for review January 28, 2026 02:10
@ztanner ztanner requested review from ijjk and timneutkens January 28, 2026 02:10
@ztanner ztanner merged commit a2e2900 into next-15-5 Jan 28, 2026
237 of 247 checks passed
@ztanner ztanner deleted the ztanner/backport-89040 branch January 28, 2026 14:13
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants