next.js correction pack

Paste into CLAUDE.md, .cursorrules, or any agent rules file on a project that uses next.js.

next.js correction pack · for projects on next@^16

What we actually measured

3 Claude models were asked for idiomatic next.js code with no tools, purely from training knowledge. 21 reproduced failures across 13 runs, each verified against the release that broke the belief.

ModelStated cutoffnext.js version attribution stopsLag inside the window
Claude Sonnet 52026-0115.0.0 · 2024-10-21~15 months
Claude Opus 52026-0516.0.0 · 2025-10-22~7 months
Claude Fable 52026-0116.0.0 · 2025-10-22~3 months

A recent cutoff is not a defence. Every model here loses track of this library's release history well before the date it states as its own cutoff, and the stopping points cluster far tighter than the cutoffs do.

Read that column precisely. It is the newest next.js release whose contents the model can correctly attribute to that release — not the newest next.js feature it knows. Past that point a model will often write working code with a newer API while naming the wrong release for it, and that guess runs early — it names a release older than the one that shipped the feature. So the question this pack answers is not "does the model know this API" but "can it be trusted about which version the API arrived in" — which is the question that matters when you are pinned to a version.

Latest next.js is 16.3.4 (verified 2026-09-02). Separately from the corrections below, 2 of 13 runs recorded a version fact — the model named a current next.js version from memory and was behind. If a model states a version without checking, assume it is behind and check the registry.

How to read an entry

Every entry ends with a Reproduced against line. Where it names models, we have the generated code that got it wrong, dated, with the model's own words in the run write-up. Where it says no model yet, the correction is verified from the release notes but nothing has been probed for it — it is a fix, not a measurement, and the pack says so rather than blurring the two.

The section an entry sits in is the worst case if you act on the stale belief. The severity in brackets after a model's name is what that particular model's output actually did, which can be milder — a model can hold the wrong belief and still, on the day, write code that runs.

The corrections

Breaks the build, or throws at runtime

Act on the stale belief here and the code does not run. Fix these first.

revalidateTag

Behaviour changed in next.js 16.0.0 (2025-10-22)

revalidateTag takes two arguments. The single-argument form is deprecated in 16.0.0 and documented as producing a TypeScript error, so on a TypeScript project — where next build type-checks by default — it fails the build. Use revalidateTag(tag, profile) for content that tolerates eventual consistency, updateTag(tag) in a Server Action when the user must see their own write immediately, and refresh() to refresh uncached data without touching the cache.

The stale belief: That revalidateTag('products') is the current call signature.

// Stale
revalidateTag('products')

// Current
revalidateTag('products', 'max')   // 'max' | 'hours' | 'days' | { expire: 3600 }
updateTag('products')              // Server Actions only: read-your-writes
refresh()                          // Server Actions only: refresh uncached data

This is the most reliably reproduced entry in the whole Index: every model tested writes the one-argument form in generated code, and two of the three can state the two-argument signature correctly when asked directly.

Reproduced against: Claude Fable 5 (S1), Claude Opus 5 (S1), Claude Sonnet 5 (S1) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25 · Next.js 16 release announcement · 2025-10-21

custom webpack config

Default changed in next.js 16.0.0 (2025-10-22)

Turbopack is stable and the default for both next dev and next build. --turbopack is no longer needed; --webpack is the opt-out. A project carrying a custom webpack config now fails the build unless it opts out.

The stale belief: That webpack is the default bundler and Turbopack is opt-in behind --turbopack.

// Stale
"dev": "next dev --turbopack"

// Current
"dev": "next dev"
"build": "next build"          // Turbopack
"build:webpack": "next build --webpack"   // opt out

experimental.turbopack as a config location moved to a top-level turbopack key.

Reproduced against: Claude Sonnet 5 (S4) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

next lint

Removed in next.js 16.0.0 (2025-10-22)

The next lint command was removed — a package.json script that calls it fails. Call ESLint or Biome directly. next build no longer runs linting either, and the eslint option in the Next.js config file is removed.

The stale belief: That next lint is the project lint script and that next build lints for you.

// Stale
"lint": "next lint"

// Current
"lint": "eslint"

Codemod: npx @next/codemod@canary next-lint-to-eslint-cli .. @next/eslint-plugin-next now defaults to ESLint flat config.

Reproduced against: Claude Sonnet 5 (S1) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

parallel route default.js

New requirement in next.js 16.0.0 (2025-10-22)

Every parallel route slot requires an explicit default.js. Builds fail without one. To keep the previous behaviour, create a default.js per slot that returns null or calls notFound().

The stale belief: That default.js is optional and its absence only causes a runtime 404 on reload — the pre-16 behaviour.

// app/@modal/default.tsx
export default function Default() { return null }

Reproduced against: Claude Fable 5 (S2) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

AMP support (next/amp, useAmp, config.amp)

Removed in next.js 16.0.0 (2025-10-22)

All AMP APIs and configuration were removed: the amp config key, next/amp imports including useAmp, and export const config = { amp: true }.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

async request APIs

Removed in next.js 16.0.0 (2025-10-22)

The synchronous-access compatibility period is over. cookies(), headers(), draftMode(), params and searchParams are async only — 15.x allowed sync access with a warning, 16.0.0 removed it.

const { slug } = await params
const cookieStore = await cookies()

Also newly async in 16.0.0 and much less well known: the props passed to opengraph-image, twitter-image, icon and apple-icon generating functions, and the id passed to a sitemap function by generateSitemaps. generateImageMetadata still receives synchronous params.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

serverRuntimeConfig / publicRuntimeConfig

Removed in next.js 16.0.0 (2025-10-22)

Both were removed. Use environment variables instead.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

Runs, but is silently wrong

Nothing errors. The behaviour is simply not what a model trained earlier will tell you.

experimental.clientSegmentCache

Removed in next.js 16.0.3 (2025-11-13)

experimental.clientSegmentCache no longer exists. It was boolean | 'client-only', defaulted to true, and was removed one day after 16.0.2 — per-segment prefetching is now unconditional and has no on/off switch under any name. Because an unrecognised key under experimental only warns (the build exits only for unrecognised keys under images, and for two named Turbopack keys), setting it looks accepted and does nothing at all. If the goal is fewer prefetch requests per link, the current lever is experimental.prefetchInlining (16.2.0); if it is no prefetching, it is <Link prefetch={false}>.

The stale belief: That per-segment prefetching can be switched off with experimental: { clientSegmentCache: false } to get one whole-tree prefetch request per link. It was true up to 16.0.2 and has been silently inert since 16.0.3.

The code below needs next.js 16.2.0 or later. Between 16.0.3 and 16.2.0 this correction does not apply — see the note.

// Stale
experimental: { clientSegmentCache: false }

// Current
experimental: { prefetchInlining: true }

Bisected in the published packages: declared in dist/server/config-shared.d.ts at 15.5.0, 16.0.0 and 16.0.2, absent from 16.0.3 onward through 16.3.4, with no renamed replacement (no config key in 16.3.4 contains 'segment'). This is a removal that shipped in a patch, one day after the release that still had it.

Reproduced against: Claude Fable 5 (S2), Claude Opus 5 (S2), Claude Sonnet 5 (S2) — next.js/v2-a, 2026-09-02; next.js/v3-a, 2026-09-02; next.js/v3-c, 2026-09-02.

Source: next 16.0.2 published package — the key still exists · 2025-11-12 · next 16.0.3 published package — the key is gone one day later · 2025-11-13 · next 16.3.4 published package — why the dead key is silent rather than fatal · 2026-08-31

experimental.ppr / export const experimental_ppr

Removed in next.js 16.0.0 (2025-10-22)

The route-segment opt-in was removed: export const experimental_ppr = true is read nowhere in 16.x, so a page that still exports it is simply ignored. The config key was not removedexperimental: { ppr } is still declared on NextConfig, still accepted by the config validator, and still honoured by checkIsAppPPREnabled at every 16.x release including 16.3.4. The trap is the combination: experimental: { ppr: 'incremental' } validates cleanly and then enables partial prerendering for no route at all, because checkIsRoutePPREnabled returns false for anything that is not a boolean and there is no longer a per-route export to consult. Nothing breaks; PPR just silently never happens. Configure partial prerendering with the top-level cacheComponents: true, which is also the new name of experimental.dynamicIO.

The stale belief: That partial prerendering is enabled through the experimental.ppr flag plus a per-route export const experimental_ppr = true. The flag half still validates; the per-route half does nothing.

// Stale
// next.config.ts — validates, and enables PPR for zero routes
experimental: { ppr: 'incremental' }
// app/page.tsx — read by nothing in 16.x
export const experimental_ppr = true

// Current
// next.config.ts
const nextConfig: NextConfig = { cacheComponents: true }

Do not tell readers this config key breaks the build — it does not, at any 16.x release. Next.js's own upgrade guide, shipped inside the package at 16.3.4 as dist/docs/01-app/02-guides/upgrading/version-16.md, states that 16 "removes the experimental Partial Prerendering (PPR) flag and configuration options"; the same tarball ships dist/server/lib/experimental/ppr.js implementing it and a configSchema that accepts it. Verified by executing the shipped validator: at both 16.0.0 and 16.3.4, experimental.ppr set to 'incremental' and to true are ACCEPTED, while the poison controls experimental.pprXYZ (unrecognized_keys) and experimental.ppr: 'nope' (invalid_union) are rejected — so the check can fail. The Suspense structure around a dynamic subtree is unchanged; models generally get that part right.

Reproduced against: Claude Opus 5 (S1), Claude Sonnet 5 (S1) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 (states a removal the shipped package contradicts) · 2026-08-25 · next 16.3.4 shipped package — dist/server/lib/experimental/ppr.d.ts · 2026-08-31 · next 16.3.4 shipped package — NextConfig still declares experimental.ppr · 2026-08-31 · next 16.0.0 shipped package — the release said to have removed it still declares experimental.ppr · 2025-10-22

middleware.ts

Renamed in next.js 16.0.0 (2025-10-22)

middleware.ts is renamed to proxy.ts, and the named export middleware to proxy. The old file still works and warns; removal is planned. The rename shipped in 16.0.0 — not 15.5 — so renaming the file on a 15.x project means nothing picks it up and the route gate silently stops running.

The stale belief: That the route gate lives in middleware.ts, or that the rename landed in 15.5.

// Stale
// middleware.ts
export function middleware(request: NextRequest) { /* ... */ }

// Current
// proxy.ts
export function proxy(request: NextRequest) { /* ... */ }
export const config = { matcher: ['/dashboard/:path*'] }

Two things models do not tell you: the proxy runtime is nodejs and cannot be configured (keep middleware.ts if you need the edge runtime), and skipMiddlewareUrlNormalize is now skipProxyUrlNormalize.

Reproduced against: Claude Opus 5 (S4), Claude Sonnet 5 (S3) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

experimental.prefetchInlining

Added in next.js 16.2.0 (2026-03-18)

Next.js 16 prefetches per segment: hovering one <Link> issues a separate request for each segment of the target route tree, which makes shared layouts cacheable across sibling routes but multiplies request volume. experimental.prefetchInlining bundles every segment of a route into a single prefetch response — one request per link — at the cost of duplicating shared layout data across responses. There is no <Link>-level prop for this; it is a config flag.

The stale belief: That the number of prefetch requests per link is not configurable, and that the only lever is turning prefetching off with prefetch={false}.

experimental: { prefetchInlining: true }

Verified in the published packages: prefetchInlining, cachedNavigations and appNewScrollHandler are all absent from dist/server/config-shared.d.ts at 16.1.7 and present at 16.2.0 and 16.3.4. Still experimental at 16.3.4.

Reproduced against: Claude Opus 5 (S2) — next.js/v3-e, 2026-09-02.

Source: Next.js 16.2 release post — experimental.prefetchInlining · 2026-03-18 · next 16.3.4 published package — the experimental config key · 2026-08-31

ImageResponse default font

Default changed in next.js 16.2.0 (2026-03-18)

The default typeface used by ImageResponse when no font is supplied changed from Noto Sans to Geist Sans. The bundled default font file is Geist-Regular.ttf. Generated OG images render in Geist unless a fonts option says otherwise.

The stale belief: That an OG image with no fonts option renders in Noto Sans (the default from @vercel/og's original bundle).

Bisected in the published packages: dist/compiled/@vercel/og/index.node.js loads noto-sans-v27-latin-regular.ttf at 16.1.7 and Geist-Regular.ttf at 16.2.0 — two days apart. The same release made ImageResponse 2x-20x faster and widened CSS/SVG coverage.

Reproduced against: Claude Opus 5 (S2) — next.js/v2-a, 2026-09-02.

Source: Next.js 16.2 release post — Faster ImageResponse · 2026-03-18 · next 16.2.0 published package — the bundled default font · 2026-03-18 · next 16.1.7 published package — the same line two days earlier · 2026-03-16

Added in next.js 16.2.0 (2026-03-18)

next/link accepts a transitionTypes prop — an array of strings passed to React's addTransitionType during the navigation Transition, so a View Transition can be styled differently per navigation. It is an App Router feature: the Pages Router Link destructures the prop away and ignores it silently, so a shared link component works in both routers without warnings. It is never forwarded to the underlying <a>, in either router, so it produces no unknown-DOM-attribute warning; in development a non-array value throws a prop-type error.

The stale belief: That <Link> has no per-navigation view-transition prop, so an unrecognised transitionTypes prop is spread onto the <a> element and React warns about an unknown DOM attribute.

<Link href="/about" transitionTypes={['slide']}>About</Link>

Verified in the published packages: absent from dist/client/app-dir/link.d.ts at 16.1.7, present at 16.2.0. At 16.3.4 the Pages Router dist/client/link.js destructures transitionTypes out of restProps and lists it in its dev-only prop guard, while the App Router dist/client/app-dir/link.js forwards it into dispatchNavigateAction.

Reproduced against: Claude Opus 5 (S2) — next.js/v2-a, 2026-09-02.

Source: Next.js 16.2 release post — transitionTypes Prop for next/link · 2026-03-18 · next 16.3.4 published package — the Pages Router Link discards the prop · 2026-08-31 · next 16.1.7 published package — the prop does not exist yet · 2026-03-16

images.maximumDiskCacheSize

Added in next.js 16.1.7 (2026-03-16)

The optimized-image disk cache is bounded, and by default the bound is 50% of the free space on the volume holding the cache directory, measured once at startup with fs.statfs. Set images.maximumDiskCacheSize to a byte count to cap it, or to 0 to disable disk caching entirely. When the cache exceeds the limit, least-recently-used optimized images are evicted until it is under the limit.

The stale belief: That the optimized-image cache in .next/cache/images grows without limit and the only controls are minimumCacheTTL or a custom cache handler.

images: { maximumDiskCacheSize: 1_000_000_000 } // 1 GB; 0 disables the disk cache

Shipped in a patch release, 16.1.7, two days before the 16.2.0 minor. Verified in the published packages: maximumDiskCacheSize is absent from imageConfigDefault at 16.1.6 and present (as undefined) at 16.1.7, where dist/server/lib/disk-lru-cache.external.js first appears. An unrecognised key under images is fatal, not a warning: normalizeNextConfigZodErrors sets shouldExit for any issue whose path starts at images, so a guessed name such as images.maximumCacheSize exits the build.

Reproduced against: Claude Opus 5 (S1) — next.js/v2-a, 2026-09-02.

Source: Next.js docs — Image component, maximumDiskCacheSize · 2026-09-02 · next 16.3.4 published package — the default sizing · 2026-08-31 · next 16.1.7 published package — the key enters imageConfigDefault · 2026-03-16

images.maximumResponseBody

Added in next.js 16.1.5 (2026-01-26)

The default image loader refuses a source image whose response body exceeds 50 MB (maximumResponseBody: 50000000). The optimizer streams the upstream response and, once the running total passes the limit, throws an image error carrying HTTP 413 — the image 404s/413s rather than being optimized. Lower it (e.g. 5_000_000) on memory-constrained servers.

The stale belief: That next/image will fetch and optimize a remote source image of any size, and that the only failure mode for a large image is slowness or an out-of-memory crash.

images: { maximumResponseBody: 5_000_000 }

The official docs' version-history table dates this to v16.1.2; the published packages contradict it by three patch releases. There is no occurrence of maximumResponseBody in 16.1.2's image-config.js, config-shared.js, config-schema.js or image-optimizer.js, nor in 16.1.4; 16.1.5 has it in imageConfigDefault and three times in image-optimizer.js. This is the second time vendor release material has been wrong about its own release in this dataset (better-auth 1.1.0, JOURNAL/027) and the first time the error is in a docs version table rather than a changelog.

Reproduced against: Claude Opus 5 (S2) — next.js/v3-e, 2026-09-02.

Source: Next.js docs — Image component, maximumResponseBody · 2026-09-02 · next 16.3.4 published package — the limit is enforced while streaming · 2026-08-31 · next 16.1.5 published package — the release the key actually appears in · 2026-01-26 · next 16.1.4 published package — absent one release earlier · 2026-01-19

images.minimumCacheTTL

Default changed in next.js 16.0.0 (2025-10-22)

The default changed from 60 seconds to 14400 seconds (4 hours). Nothing errors; images just revalidate far less often than a model trained on 15.x will tell you.

The stale belief: That the default image cache TTL is 60 seconds.

images: { minimumCacheTTL: 60 }   // if you need the old behaviour back

Reproduced against: Claude Sonnet 5 (S2) — next.js/v1, 2026-08-31.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

catchError (next/error)

Added in next.js 16.2.0 (2026-03-18)

next/error exports catchError, which wraps a fallback component into a component-level error boundary usable anywhere in a Client Component tree — finer-grained than the route-level error.js convention. Its fallback receives the call-site props plus an ErrorInfo second argument ({ error, reset, retry }). Prefer it over a hand-rolled React class boundary: Next's own boundary re-throws the framework's control-flow errors, so redirect() and notFound() still work inside it, while a naive user boundary catches them and renders the fallback instead.

The stale belief: That the framework offers no component-level error boundary and the answer is a hand-written React class boundary or the react-error-boundary package.

The code below needs next.js 16.3.0 or later. Between 16.2.0 and 16.3.0 this correction does not apply — see the note.

'use client'
import { catchError, type ErrorInfo } from 'next/error'

function Fallback(props: { title: string }, { error, retry }: ErrorInfo) {
  return <button onClick={() => retry()}>{props.title}</button>
}

export default catchError(Fallback)

Shipped in 16.2.0 as unstable_catchError and stabilised to catchError in 16.3.0; next/error.d.ts at 16.1.6 exports only the Pages Router error page. Client module graph only — it cannot be imported in proxy or instrumentation.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js 16.2 release post — unstable_catchError() · 2026-03-18 · next 16.3.4 published package — catchError declaration · 2026-08-31 · next 16.3.4 published package — the framework boundary re-throws router errors · 2026-08-31

error.tsx retry prop

Added in next.js 16.2.0 (2026-03-18)

An App Router error.tsx component is passed { error, reset, retry }. reset() only clears the boundary's error state and re-renders the children — it does not re-run the server render, so an error thrown while a Server Component awaited data comes straight back. retry() is the one that recovers from a data error: it calls the router's refresh() and reset() inside a startTransition. Wire a 'Try again' button to retry, not to reset.

The stale belief: That error.tsx receives only { error, reset }, and that reset() re-fetches. Models that know reset() does not re-fetch hand-roll the fix — useRouter().refresh() plus reset() inside startTransition() — which is exactly what retry now is.

The code below needs next.js 16.3.0 or later. Between 16.2.0 and 16.3.0 this correction does not apply — see the note.

// Stale
'use client'
export default function Error({ error, reset }) {
  return <button onClick={() => reset()}>Try again</button> // re-renders, does not re-fetch
}

// Current
'use client'
import type { ErrorInfo } from 'next/error'
export default function Error({ error, retry }: ErrorInfo) {
  return <button onClick={() => retry()}>Try again</button>
}

Shipped in 16.2.0 as unstable_retry and stabilised to retry in 16.3.0 — code written against 16.2.x needs the prefix, code written against 16.3.x must not have it. Bisected in the published packages: 16.1.6 declares { error, reset? }, 16.2.0 declares { error, reset, unstable_retry }, 16.3.4 declares { error, reset, retry }.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js 16.2 release post — unstable_retry() in error.tsx · 2026-03-18 · next 16.3.4 published package — ErrorBoundaryHandler · 2026-08-31 · next 16.1.6 published package — the same type one release earlier · 2026-01-27

images.qualities

Default changed in next.js 16.0.0 (2025-10-22)

The default changed from allowing all qualities to [75]. A quality prop outside the list is coerced to the closest allowed value — it is not rejected — so quality={90} silently serves 75.

The stale belief: Either that any quality value is served, or that an unlisted quality is rejected with a 400. Both are wrong; it is coerced.

images: { qualities: [50, 75, 100] }

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

local images with query strings / local IP optimization

Stricter in next.js 16.0.0 (2025-10-22)

A local image src carrying a query string now requires an images.localPatterns entry with a search pattern, to prevent enumeration attacks. Separately, optimizing images on local IPs is blocked unless images.dangerouslyAllowLocalIP is set.

images: {
  localPatterns: [{ pathname: '/assets/**', search: '?v=1' }],
  dangerouslyAllowLocalIP: true,   // private networks only; understand the SSRF risk
}

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

unstable_rootParams() / devIndicators options

Removed in next.js 16.0.0 (2025-10-22)

unstable_rootParams() was removed, as were the devIndicators options appIsrStatus, buildActivity and buildActivityPosition.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25 · Next.js docs — Upgrading: Version 16 · 2026-08-25

Deprecated, or a better API now exists

Works today. It is the older idiom, and some of it is scheduled for removal.

cacheLife / cacheTag

Renamed in next.js 16.0.0 (2025-10-22)

cacheLife and cacheTag are stable and lost the unstable_ prefix. Aliased imports should be updated. unstable_cache itself still exists and still works — it is simply no longer the current idiom.

// Stale
import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache'

// Current
import { cacheLife, cacheTag } from 'next/cache'

export async function getProducts() {
  'use cache'
  cacheLife('hours')
  cacheTag('products')
  return db.product.findMany()
}

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

images.domains

Deprecated in next.js 16.0.0 (2025-10-22)

images.domains is deprecated, not removed — use remotePatterns. Models overstate this in both directions; the accurate statement is deprecated-and-still-working.

images: { remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }] }

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

images.imageSizes

Default changed in next.js 16.0.0 (2025-10-22)

The value 16 was removed from the default images.imageSizes array, shrinking the generated srcset.

images: { imageSizes: [16, 32, 48, 64, 96, 128, 256, 384] }   // to keep 16px

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

images.maximumRedirects

Default changed in next.js 16.0.0 (2025-10-22)

The default for images.maximumRedirects changed from unlimited to 3.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

scroll-behavior: smooth

Behaviour changed in next.js 16.0.0 (2025-10-22)

Next.js no longer overrides a global scroll-behavior: smooth during SPA route transitions. Opt back into the old override with data-scroll-behavior="smooth" on the html element.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

Wrong facts about the library

Not code — versions, minimums and metadata that models state confidently and get wrong.

AGENTS.md shipped by next dev

Added in next.js 16.0.0 (2025-10-22)

Next.js 16 tells you to install an AGENTS.md block, which next dev writes and re-adds by itself. The framework ships a warning to coding agents that their priors about it are stale — the same claim this Index makes empirically, per model and per date.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

Node.js and TypeScript minimums

New requirement in next.js 16.0.0 (2025-10-22)

Next.js 16 requires Node.js 20.9.0+ (Node 18 is no longer supported) and TypeScript 5.1+. Browser floor: Chrome/Edge/Firefox 111+, Safari 16.4+.

Reproduced against: no model yet. Verified from the primary source only — this is a correction, not an Index entry.

Source: Next.js docs — Upgrading: Version 16 · 2026-08-25

Not corrections — recorded for honesty

Claims seen in a run but not yet verified against a primary source. Never treated as findings:

  • Prediction P1 said all four Sonnet 5 and Fable 5 draws would reach experimental.clientSegmentCache. Three of four did; this draw's twin v3-d did not, answering "No" and naming the key only to say it is gone. The prediction is falsified on the fourth draw, and the two subjects split the same way internally: both Sonnet draws fail the surface, one Fable draw of two fails it. Whether that is a subject difference or two coin flips cannot be read from four draws. (open since 2026-09-02)
  • This draw and next.js/v3-a produce the same wrong configuration with opposite epistemics - one at 60 percent with the correct counterfactual spelled out, one asserting a schema validation that does not exist. The Index scores both S2 because the artefact is identical, and the severity scale has no way to say that one of them warned its reader. Whether that is the right treatment or a gap in the scale is unresolved; JOURNAL/032 declined to add a fifth level and this is a second kind of pressure on the same edge. (open since 2026-09-02)
  • This is the fourth battery in which the non-charging -b twin held the better answer (HARNESS.md records three: better-auth/v2, and two before it). The rule that the second draw charges nothing was chosen to keep replication from inflating counts, and it is now systematically discarding the better-informed draw. That is the correct trade for the finding count, but the site's per-subject picture is built from arms selected by a rule that is uncorrelated with which draw was right. (open since 2026-09-02)
  • Both Fable draws state an identical cutoff and an identical boundary while giving opposite answers on the probe surface. If the self-report is stable for this subject and the answer is not, then the boundary readings the Index publishes for Fable 5 x next.js are more precise than they are informative about what the subject will actually write. Needs a third and fourth draw of something before it is more than an observation about two. (open since 2026-09-02)
  • Fable 5's library knowledge reaching its own cutoff while Opus 5 — stated cutoff four months later — stops seven months short is now the second instance of the same dissociation, after zod. Is it a property of the model or of these two libraries? (open since 2026-08-31)
  • The severity scale has no level for 'working code the framework now supersedes'. Two of this battery's nine probes landed there. Either add one or state on the method page that capability probes of this kind are recorded and never charged. (open since 2026-09-02)
  • Every draw of four reached for experimental.clientSegmentCache, removed in a patch 16.0.3 and inside all three subjects' windows. It wants a charging battery against Sonnet 5 and Fable 5, whose arms here charge nothing. (open since 2026-09-02)
  • Three batteries running, the -b twin has held the better answer on at least one probe. Is the -a/-b assignment doing any work, or should the charging arm be the one that answers first, or a merge of the two? Changing it would break comparability with everything already published. (open since 2026-09-02)
  • Is the reversal on clientSegmentCache knowledge or wording? v2's task 8 asked whether reducing prefetch requests was configurable "and if so, how? Write whatever is needed", and got the dead key from four draws of four across three subjects. v3's task 1 demands a one-word yes or no before any explanation, and got a correct denial from both Opus draws. Same subject, same surface, same day, opposite outcomes. If the wording is what moved it, then a probe that invites config produces config, and several charged findings in this dataset may be measuring the invitation. (open since 2026-09-02)
  • The Index has now caught right-about-the-removal-wrong-about-the-replacement at valibot and next.js. Both were found by a capability probe that asks how to do a thing rather than whether an API exists. Whether that category is common enough to be a product claim, or is two instances, is not established. (open since 2026-09-02)
  • The Opus twins agreed on their stated cutoff and on the whole clientSegmentCache surface, and disagreed on task 3, where one leaned to a cap and one to no cap. The Sonnet twins in the same battery agreed on the library and disagreed on their own cutoff. Whether duplication is buying a reading of the subject or a reading of the probe differs by pair, and the index reports one spread for both. (open since 2026-09-02)
  • The cutoff self-report has now split between blind twins in two libraries (zod/v4, next.js/v3). Two draws of two batteries is not a rate. The index publishes stated cutoffs as if they were a property of the subject; they are a property of the draw, and nothing on the site says so yet. (open since 2026-09-02)
  • This subject's next.js boundary now has four readings across three batteries (15.0.0, 15.0.0, 15.3.0, 15.5.0). JOURNAL/030(c) read v1-vs-v2 agreement as evidence that a battery does not move a boundary. Whether v3 moved it, or whether v1 and v2 happened to agree, cannot be settled from four points. (open since 2026-09-02)
  • Recording a refused cutoff as a single date loses information. This draw gave a range and a reason; the schema stores one string. The fairness rule needs a comparable value, but a range with a stated basis is the honest datum and the site cannot show it. (open since 2026-09-02)

Findings, code and citations: data/next.js/ — one JSON file and one write-up per model, each finding carrying the release that broke the belief, its publication date and a verbatim quote from the primary source. Corrections: data/next.js/facts.json. This file is generated by tools/build-corrections.mjs; if the prose and the data ever disagree, that is a bug in the generator, not a stale pack.

Honest note on maintenance: this pack is generated, not written by hand. tools/build-corrections.mjs renders it from the verified release facts in data/next.js/facts.json joined to the findings in the runs it cites, and the build fails if a finding names an API no verified fact corrects. Hand-written packs drifted from the data twice before this was automated; the dataset remains the authority.