
Next.js 16 cacheComponents Build OOM: The Real Fix
Skilldham
Engineering deep-dives for developers who want real understanding.
Last updated: July 2026
TL;DR
Next.js 16 cacheComponents build failures come from two separate causes, not one. The SIGKILL OOM happens because cacheComponents turns on source maps during the prerender phase by default. The RangeError: Invalid string length happens later. It shows up once you add use cache on a page with many static paths. The serialized cache payload grows past what V8 can hold in one string.
Fix the OOM first with enablePrerenderSourceMaps: false
Fix the RangeError by scoping use cache narrower and trimming generateStaticParams
Both fixes ship independently - you may only need one
You write cacheComponents: true in next.config.ts. Locally, everything builds. You push to Vercel.
The build dies. No stack trace. No error message. Just SIGKILL.
You Google it. You find a GitHub discussion with your exact symptom and no accepted answer.
You strip out dynamicParams, clean up revalidate, add the Suspense boundaries the migration guide asks for. Still SIGKILL.
You add use cache to your fetch helper, hoping caching means less memory, not more. The build gets further this time - then dies with RangeError: Invalid string length.
Here's what's actually happening at build time, and the two separate config changes that fix it.
Why Next.js 16 cacheComponents build memory blows up
cacheComponents does two things at once during next build. Neither flag did this on its own before Next.js 16.
First, it turns on source maps by default during the prerender phase. This is documented in the Next.js memory usage guide. It is not mentioned anywhere in the Cache Components migration guide. Most people never see it before they hit it.
Second, once you add use cache, Next.js has to serialize the cached output. It needs that to store and replay it later. On a route with a large generateStaticParams count, that serialized payload grows with every path.
The SIGKILL signature
If your build dies with SIGKILL and no error message, suspect source maps first. That's true even before you touch use cache at all. Source map generation during the prerender phase is memory-hungry on its own. Stack it on top of a large route tree, and the build container runs out of RAM. Next.js never even gets the chance to report why. Still not sure if this is a cacheComponents-specific problem or a general Vercel limit? The Next.js build fails on Vercel post covers the non-cache causes worth ruling out first.

The RangeError signature
RangeError: Invalid string length shows up after SIGKILL is gone. It appears once use cache enters the picture. V8 has a hard cap on how long a single JavaScript string can be. A use cache function wrapping a page with 1,000+ static paths can cross that cap. The serialized payload gets too large during the prerender step.
Fix 1: Disable prerender source maps
This is the fix nobody documents next to the error. It lives quietly in the Next.js memory usage guide, three headings past anything about cacheComponents.
javascript
// next.config.js
// Wrong: leaves source maps on during the exact phase that OOMs
const nextConfig = {
cacheComponents: true,
}
module.exports = nextConfigjavascript
// next.config.js
// Correct: disables source maps specifically during the prerender phase
const nextConfig = {
cacheComponents: true,
enablePrerenderSourceMaps: false,
}
module.exports = nextConfigenablePrerenderSourceMaps only affects the "Generating static pages" step. It does not touch your dev experience or your client-side debugging.
If the build still runs out of memory after this, pair it with the two flags below.
javascript
// next.config.js
const nextConfig = {
cacheComponents: true,
enablePrerenderSourceMaps: false,
productionBrowserSourceMaps: false,
experimental: {
serverSourceMaps: false,
webpackMemoryOptimizations: true,
},
}
module.exports = nextConfigI run this exact combination on a project with roughly 900 generated paths. Turning off enablePrerenderSourceMaps alone did most of the work. The build went from a guaranteed SIGKILL to a clean pass. No other changes were needed.
Fix 2: Scope use cache narrower, not wider
Once source maps stop being the bottleneck, look at use cache itself. The RangeError points at how much it holds in memory at once.
Wrong code
javascript
// Wrong: caching the whole page means serializing every static path's full output
export default async function Page({ params }) {
'use cache'
const { slug } = await params
const data = await getPost(slug)
return <PostBody data={data} />
}Correct code
javascript
// Correct: cache only the data fetch, not the rendered page shell
async function getPost(slug) {
'use cache'
cacheLife('hours')
const res = await fetch(`https://api.example.com/posts/${slug}`)
return res.json()
}
export default async function Page({ params }) {
const { slug } = await params
const data = await getPost(slug)
return <PostBody data={data} />
}Caching the data fetch instead of the whole page component shrinks what gets serialized per path. The page shell renders fresh each time. Only the fetch result gets cached and reused.

Why this works
use cache on a whole page component caches everything that page produces. That includes markup structure tied to that specific path. use cache on a narrow helper function caches only the data. For a route with 1,500+ static paths, that difference matters. It's the gap between a build that finishes and one that throws RangeError.
Trim generateStaticParams before you scope cache
If narrowing use cache isn't enough on its own, pull a second lever. Reduce how many paths you ask Next.js to prerender up front.
javascript
// Wrong: prerenders every path at build time, all 1,500+ of them
export async function generateStaticParams() {
const posts = await getAllPosts()
return posts.map((post) => ({ slug: post.slug }))
}javascript
// Correct: prerender your highest-traffic paths, defer the rest to request time
export async function generateStaticParams() {
const posts = await getTopPosts(100)
return posts.map((post) => ({ slug: post.slug }))
}Under cacheComponents, generateStaticParams must return at least one param. It does not have to return all of them. The remaining paths still render, just at request time instead of build time. They get cached on first visit through use cache.
Before you flip the flag: a pre-flight checklist
Run this before enabling cacheComponents on an existing large project, not after the build starts failing.
Count your total static paths across generateStaticParams calls. Above roughly 500-1,000, expect memory pressure.
Add enablePrerenderSourceMaps: false from the start, not as a reaction to a SIGKILL.
Decide upfront whether use cache belongs on the page component or on a narrow data-fetching helper. Default to the helper.
Check whether any client components rely on unmounting to reset state. cacheComponents wraps routes in React's Activity component, which preserves state across navigation instead of resetting it.
Run one next build locally with --experimental-debug-memory-usage before your first Vercel deploy. You'll see memory pressure building instead of getting a silent kill. Hit a SIGKILL/OOM outside of Next.js before, like in Docker or Kubernetes? The debugging steps in the Node.js OOMKilled memory guide carry over directly.
The Activity state-persistence gotcha
This one has nothing to do with memory. It shows up in the same migration window, so it's worth flagging here.
With cacheComponents enabled, Next.js wraps routes in React's Activity component instead of unmounting them on navigation. A dropdown that used to close on navigation now stays open. A dialog's mount-time focus logic stops re-firing, because the component never actually remounted.
The Next.js team's own tracking thread lists three common breakage points. Dropdowns, dialogs with initialization logic, and post-submit form state top the list. Close menus in a useLayoutEffect cleanup function instead. Derive dialog open/closed state from the URL, not local useState.
Key Takeaways
A Next.js 16 cacheComponents build that dies with SIGKILL and no error is almost always the default source-map generation during the prerender phase, not your code
enablePrerenderSourceMaps: false is the single highest-leverage fix, and it is missing from the official migration guide
RangeError: Invalid string length shows up once use cache serializes a payload that crosses V8's string length limit
Cache the data fetch, not the whole page component, to shrink what gets serialized per static path
generateStaticParams can prerender a subset of paths and defer the rest to request time under cacheComponents
The Activity-driven state persistence side effect is unrelated to memory but lands in the same migration window
None of this is covered together in one place in the official docs as of Next.js 16.2
FAQ
Does enablePrerenderSourceMaps break error stack traces in production?
No. It only disables source maps during the "Generating static pages" step of next build. Your runtime error tracking and browser DevTools are unaffected.
Is this fixed in a specific Next.js 16 patch version?
As of Next.js 16.2, the GitHub discussion is still open. No official patch exists yet. The config-level workarounds in this post are the current path forward.
Does this affect Next.js 15 or only Next.js 16?
cacheComponents is a Next.js 16 feature. It replaces the earlier experimental.dynamicIO and experimental.ppr flags. Neither of those carried the same prerender source-map default.
Will reducing generateStaticParams hurt my SEO?
No, as long as the remaining paths still render and get indexed on first request. Search engines crawl request-time rendered pages the same way they crawl prerendered ones. That's true once the page gets cached after the first hit.
Can I just disable cacheComponents instead of fixing this?
You can, and it removes the OOM immediately. But you also lose use cache, cacheLife, and Partial Prerendering. Next.js 16 folded all three into the cacheComponents flag.
Does the Activity state-persistence issue also cause the OOM?
No, they are unrelated. The OOM and RangeError are memory issues during next build. The Activity behavior is a runtime UI issue that shows up after a successful build.
Do I need both fixes, or just one?
Depends on your symptom. If you only see SIGKILL, enablePrerenderSourceMaps: false alone may be enough. If you've already added use cache and see RangeError, you need the narrower caching pattern too.
What if I'm on Vercel's Hobby plan with a lower memory limit?
The same fixes apply, but you have less headroom. Trimming generateStaticParams to your highest-traffic paths matters more on a memory-constrained build container.
Conclusion
A Next.js 16 cacheComponents build failure almost never means your app is too big for Next.js. It usually means source maps are on during the wrong build phase. Or use cache is caching more than it needs to. Fix the source map default first, then narrow what you cache. The build passes without you needing to strip the feature back out.
If you're mid-migration and hitting a different use cache failure, check the Next.js use cache not working guide first. It covers the silent-failure step that usually comes before this one. Want the next build error explained the same way? Subscribe below.