100 Commits
Author SHA1 Message Date
67f16a522d Fix PPR rendering for configured HTML bots (#96364)
## Summary

When PPR is enabled, requests matching a custom `htmlLimitedBots`
pattern could still use the prerendered route path. As a result, the
configured blocking-metadata behavior was not applied consistently.

Use the existing streaming-metadata decision when selecting the PPR
render path. Built-in bots retain their existing fully buffered
behavior, custom HTML-limited bots can continue streaming body content
after metadata resolves, and regular user agents remain unchanged.

## Verification

- HEADLESS=true pnpm test-start-turbo
test/e2e/app-dir/html-limited-bots-ppr/html-limited-bots-ppr.test.ts
- HEADLESS=true pnpm test-start-webpack
test/e2e/app-dir/html-limited-bots-ppr/html-limited-bots-ppr.test.ts

Co-authored-by: Sebastian Silbermann <[email protected]>
2026-07-29 15:49:57 -07:00
Zack TannerandGitHub ccfe67aa8d Return 200 for client-handled Server Action redirects (#96310)
## Summary

Client-handled Server Action redirects currently return a `303` without
a `Location` header and may include a streamed RSC response body. Some
HTTP intermediaries reject this response or strip its body because it
looks like an HTTP redirect.

Return `200` for client-handled Server Action redirects while continuing
to use `x-action-redirect` and the RSC response. Progressive-enhancement
form submissions still return a standards-compliant `303` with
`Location`.

Fixes #92882
Fixes #74026

## Verification

- `HEADLESS=true pnpm test-dev-turbo
test/e2e/app-dir/actions/app-action.test.ts
test/e2e/app-dir/app-basepath/index.test.ts
test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts`
- `HEADLESS=true pnpm test-start-turbo
test/e2e/app-dir/actions/app-action.test.ts
test/e2e/app-dir/app-basepath/index.test.ts
test/e2e/app-dir/actions/app-action-progressive-enhancement.test.ts`
- `pnpm --filter=next types`

<!-- NEXT_JS_LLM -->
2026-07-28 16:04:34 -04:00
Zack TannerandGitHub b368a504a8 Fix Turbopack worker URL context lookup (#96307)
## Summary

- Preserve the original static worker request when generating the
Turbopack module-context lookup, instead of passing an already-rewritten
URL object.
- Adds an e2e fixture for bare-module Worker URLs with conditional
wildcard exports.

It looks like this might have regressed in #88602

Fixes #94015
Closes #94043 

## Verification

- `cargo check -p turbopack-ecmascript`
- `HEADLESS=true pnpm test-start-turbo
test/e2e/app-dir/worker-module-url/worker-module-url.test.ts`
- `HEADLESS=true pnpm test-start-webpack
test/e2e/app-dir/worker-module-url/worker-module-url.test.ts`
2026-07-28 11:48:17 -07:00
Zack TannerandGitHub d72a0355e3 [ci]: remove PR creation from deploy test workflow (#93400)
We're not planning to re-enable this workflow, and instead are handling
the upgrade PRs from within the applications themselves.

This removes them since they are currently failing.
2026-04-30 21:41:03 +00:00
Zack TannerandGitHub 4ba05cc300 enable validateRSCRequestHeaders by default (#93367)
This flag has been enabled by default on canary for some time. This
turns it on by default to ensure that CDNs that don't respect `Vary`
properly distinguish between different response types.
2026-04-29 12:44:32 -07:00
Zack TannerandGitHub 908af50147 [ci]: Use macOS arm runner for intel builds (#93330)
The intel runners were quite a bit slower than the base arm runners. We
were previously compiling both architectures on self-hosted arm so this
just back the status quo on GH runners to improve speed. This shaves off
~10/20 mins.

Validated
[here](https://github.com/vercel/next.js/actions/runs/25071926790/job/73454315459)
2026-04-28 12:55:55 -07:00
Zack TannerandGitHub 0ea2845cf9 [ci]: fix release script to not strip newlines (#93302)
The process of signing commits with GH API was stripping newlines. This
configures that step to not strip newlines so lint doesn't fail. x-ref:
https://github.com/vercel/next.js/actions/runs/25007903789/job/73240317094

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
2026-04-28 18:42:19 +00:00
Zack TannerandGitHub 012fd7df4b [ci]: trigger signed release commit via API (#93285)
Stacked on https://github.com/vercel/next.js/pull/93245

Commit signing is required for anything that lands on `canary`. Our
previous workflow of using a PAT to push a commit no longer works, since
that would have been an unsigned commit.

In #93245 we switched to an app token for release workflow steps. This
continues by:

- Telling Lerna to bump packages but not commit
- Creating a signed commit with the staged changes via GitHub's API
- Then running the publish flow

Test Plan:
Dry run
[here](https://github.com/vercel/next.js/actions/runs/25001287978/job/73211826479)
Commit
[here](https://github.com/vercel/next.js/commit/3a8456a62b56615e2f8c1d1e6e7b4e14ce89e078)
2026-04-27 16:31:05 +00:00
Zack TannerandGitHub e69de2ffaf [ci]: app-based release workflow (#93245)
Moves all release workflows off of a GH PAT and uses an app with a
short-lived token instead.

Test Plan:
Dry run
[here](https://github.com/vercel/next.js/actions/runs/24934593874).

However, this workflow is blocked until we figure out commit signing for
the bot app. Some options:
- The bot account generates a signing key and we use it in CI (not
great, bypasses the app)
- The org bypasses signature verification for the bot user (also not
great, requires an exemption rule)
- We need to rework the commit step so Lerna does not do the push, and
instead trigger it via the app + GH API. This seems like the best
option, will be added in a follow-up PR.

Note: `create-release-branch` workflow is broken in its current form, as
we will not be restoring administrator privileges to adjust environment
settings. This will become a manual step in the future.
2026-04-27 07:55:43 -07:00
Zack TannerandGitHub 9de8744991 [ci]: fix permissions on comment workflow (#93225)
Needs write to comment on PR. x-ref:
https://github.com/vercel/next.js/actions/runs/24914306362/job/72962981110
2026-04-24 22:42:09 +00:00
Zack TannerandGitHub 1849a0d00e [ci]: move stats & CI status comment to workflow (#93220)
- Add a workflow_run reporter that posts PR test/stats comments using
`GITHUB_TOKEN`.
- Upload PR metadata artifacts from `build-and-test` and `Generate
Stats` so the reporter can safely resolve the target PR
- Move stats/test comment posting out of the external webhook/PAT path
while preserving the existing comment format

This means the test comment won't incrementally update as tests fail,
it'll just post once at the end, but that's a reasonable tradeoff to not
having to worry about a webhook.
2026-04-24 14:51:35 -07:00
Zack TannerandGitHub cabf0a4197 [ci]: pin rust-musl-cross (#93176)
Pins these docker dependencies. Follow-up from:
https://github.com/vercel/next.js/pull/93164#discussion_r3135035714

x-ref: 

https://github.com/rust-cross/rust-musl-cross/pkgs/container/rust-musl-cross/741104753?tag=x86_64-unknown-linux-musl

https://github.com/rust-cross/rust-musl-cross/pkgs/container/rust-musl-cross/741104508?tag=aarch64-unknown-linux-musl
2026-04-24 02:36:18 +00:00
Zack TannerandGitHub 82b320addf [ci]: switch to GitHub runners (#93164)
## Summary

Switch CI from self-hosted runners to GitHub-hosted runners and fix the
follow-up issues that showed up once the hosted jobs were exercised.

## Changes

- Move Linux workflows onto `ubuntu-latest-16-core-oss`, Windows
workflows onto `windows-latest-8-core-oss`, and the native mac release
lane onto `macos-15-intel`.
- Update the reusable build workflow to work in hosted environments by
relying on `runner.os` instead of label string matching, and by removing
the hardcoded `/home/runner` `fnm` path.
- Make Turbo/sccache configuration explicit for hosted runners:
  - unify on `vtest314-next-adapter-e2e-tests`
- pass `TURBO_TOKEN` via workflow env/secrets instead of assuming
runner-level env
- switch Turbo cache mode to `local:rw,remote:rw` so jobs still have
local cache behavior when remote cache is unavailable
- Update the `sccache` action defaults/docs to use the hosted-runner
secret setup (`TURBO_TOKEN`) instead of the old self-hosted token
wiring.
- Make Datadog reporting fail open so missing `DATA_DOG_API_KEY` does
not block CI.
- Fix the CLI reserved-port test so it asserts Next’s own `-p 1`
validation instead of failing earlier on hosted Linux due to
privileged-port binding.
- Replace the live `musl.cc` dependency in `native-builder.Dockerfile`
with musl sysroots imported from GHCR-hosted `rust-musl-cross` images,
keeping the existing `/opt/*-cross` layout used by the Linux native
build scripts.
- Fix the macOS native build workaround s so it applies to all
*-apple-darwin targets based on the Cargo target OS rather than the host
architecture, which avoids napi-build injecting the unsupported -Wl
linker arg when @next/swc is linked with rust-lld on hosted mac runners.

Test Plan:
- This PR's CI
- This
[build_and_deploy](https://github.com/vercel/next.js/actions/runs/24865715983/job/72801225722)
job running on every arch
2026-04-23 18:53:07 -07:00
Zack TannerandGitHub 1f0ced5685 [ci]: cleanup labeler (#93135)
Remove labels that we are no longer maintaining.
2026-04-22 13:53:10 +00:00
Zack TannerandGitHub 2293d650f5 [tests]: fix cache-components.test.ts type error (#93113)
Fixes a type error on canary after merging two PRs that touched the same
test.
2026-04-21 18:25:31 -07:00
Zack TannerandGitHub a430936c7f Strengthen _rsc cache-busting param (#92755)
This updates `_rsc` cache-busting param generation to use a stronger
digest so different RSC request variants are much less likely to produce
the same value.

It also updates the related request-validation and injected
resume/instant-test paths so they continue to generate and validate the
same `_rsc` values across client, server, and edge-reachable codepaths.
2026-04-21 13:55:58 -07:00
Zack TannerandGitHub 2b846de4c5 [ci]: add environment to publishRelease flow (#93093)
Moves the `environment` into `publishRelease` rather than
`trigger_release` since the actual action we want to create environment
rules for is the publish step.
2026-04-21 11:23:06 -07:00
Zack TannerandGitHub 129896c2e4 [ci]: remove publish token in favor of OIDC (#93065)
Switches from a long-lived token to trusted publishing OIDC flow. This requires a bump to Node (for feature support). Otherwise just dropping unnecessary envs.
2026-04-20 11:17:33 -07:00
Zack TannerandGitHub c49ebd2d39 [ci]: remove unused workflow (#93064)
These packages have not been actively published and aren't in a working state. This removes the workflow for now.
2026-04-20 11:15:36 -07:00
Zack TannerandGitHub 9895972da5 [partial fallbacks]: include prefetch requests in shell upgrade handling (#92894)
With the new `partialFallbacks` heuristic, routes that weren't part of
`generateStaticParams` will now upgrade their shells to include the
params as if they had been in `generateStaticParams`, but only when the
page with the unknown param was lazily visited.

This tweaks the heuristic to allow segment prefetches to also trigger
the upgrade behavior. This will ensure subsequent clients, when
prefetching the upgraded route, will receive the entry with params
filled in rather than showing the generic fallback.

In a subsequent PR, we'll make it so that the requesting client that
triggers the upgrade path can also benefit from the params being
upgraded, as the client router currently has no awareness that a
background revalidation completed.
2026-04-17 09:35:39 -07:00
Zack TannerandGitHub 20e51129ff [ci]: fix backport sync script (#92942)
Fixes a few things:

- semver wasn't available because deps weren't being installed
- Fixed it to compare latest release with latest canary -- it was
erroneously marking a backport as not a backport.

Test plan:
Dry run results here:
https://github.com/vercel/next.js/actions/runs/24571828615/job/71846911677

```
should_dispatch=true
reason=Dispatching canary preminor release because stable release 16.2.4 is ahead of 16.2.1-canary.46
released_version=16.2.4
current_canary_version=16.2.1-canary.46
dispatch_input=false
auto_dispatch_enabled=true
```
2026-04-17 17:43:06 +02:00
Zack TannerandGitHub 1464f8f132 fix accidental test duplication (#92922)
This test was erroneously added in
https://github.com/vercel/next.js/pull/92920 which already exists
[here](https://github.com/vercel/next.js/blob/canary/test/e2e/rewrite-request-smuggling/rewrite-request-smuggling.test.ts).
2026-04-16 17:45:37 -07:00
Zack TannerandGitHub a584bb8794 [ci]: add workflow to bump canary after backport (#92801)
This adds an automated path to keep canary semver-ahead after a
successful stable backport publish.

Today, a backport release can produce a stable version that is newer
than the current canary version, which creates confusing version
ordering for tooling. This change adds a follow-up workflow that
evaluates completed backport publishes and, when appropriate, triggers a
canary preminor release on canary.

The `Sync Canary After Backport Release` workflow evaluates whether a
completed `build-and-deploy` run should trigger a canary sync.

The evaluation only triggers when:
- the upstream `Potentially publish release` job succeeded
- the head commit is a stable release commit
- the published stable version is a backport relative to next@latest
- the current canary version is not already semver-ahead
- there is not already a queued or in-progress Trigger Release run on
canary

When all checks pass, the workflow dispatches trigger_release.yml on
canary with:
- releaseType=canary
- semverType=minor
- force=true

(This is currently gated behind an env flag so we can dry-run it)
2026-04-15 23:50:52 +00:00
Zack TannerandGitHub 8a1316e212 [partial fallbacks]: enable by default (#92627)
This makes `experimental.partialFallbacks` the default when
`cacheComponents` is enabled.

For routes that prerender only a subset of params via
`generateStaticParams`, requests for unknown params used to either
suspend to a nearby fallback or block until the full route finished
rendering. In the cases where the route could already produce a
contentful shell because param access happened below a Suspense
boundary, the old default still served that generic shell on every
request.

With `partialFallbacks` enabled by default, the first request still
receives the best shell available for that route, but Next.js now
revalidates in the background using the newly discovered param values.
That allows subsequent requests to reuse a more specific cached result:
- If the route becomes fully static for those params, later requests get
the fully prerendered page.
- If the leaf remains dynamic, Next.js upgrades the shell as far as it
can, filling in the newly known static params while the dynamic portion
continues to stream.

This also fixes a bug that was caught now that we ran this flag against
the entire CI. A concrete path like `/optional-catchall` could match the
generic `/optional-catchall/[[...slug]]` shell and incorrectly serve
fallback-shell behavior even though that exact path was already
prerendered. This change keeps concrete prerendered paths serving their
concrete result instead of downgrading back to the generic shell.

This PR also removes redundant `partialFallbacks: true` test config and
adds coverage for the explicit opt-out behavior (`partialFallbacks:
false`).
2026-04-10 14:39:25 -07:00
Zack TannerandGitHub da1ec0dd26 [build info]: omit symbol from top level gSP route (#92525)
When a route with params specifies `generateStaticParams`, the meaningful outputs are the sub-paths contained within. The top level route just corresponds with the file path, which isn't representative of a static or partially prerendered output. Previously it'd just inherit one of the sub-path values (ie if one path was PPRed, it'd show PPR, even if some were fully static).

This removes the symbol from those types of outputs, since #92518 moved those symbols to be within the subpaths. 

For truly dynamic param cases (ie, no subpaths), the rendering symbol will still appear.
2026-04-08 15:54:36 -07:00
Zack TannerandGitHub b5da7b7f7d [build info]: distinguish between PPR and fully static routes in gSP (#92518)
With `cacheComponents`, it's possible with `generateStaticParams` to produce a fully static route, while other sub-routes might still be partially prerendered. This updates the build info to distinguish between the two. 

Before:
```
├ ◐ /params/semantics/[lowcard]/[highcard]/layout-has/server
│ ├ /params/semantics/[lowcard]/[highcard]/layout-has/server
│ ├ /params/semantics/one/[highcard]/layout-has/server
│ └ /params/semantics/one/build/layout-has/server
```

After:
```
├ ◐ /params/semantics/[lowcard]/[highcard]/layout-has/server
│ ├ ◐ /params/semantics/[lowcard]/[highcard]/layout-has/server
│ ├ ◐ /params/semantics/one/[highcard]/layout-has/server
│ └ ○ /params/semantics/one/build/layout-has/server
```
2026-04-08 15:34:20 -07:00
Zack TannerandGitHub e296bcb812 [tests]: remove unnecessary skipDeployment flags (#92423)
These tests won't ever be run in a deployed environment, so this removes
`skipDeployment` so it's easier to grok which tests are intentionally
disabled because they don't work when deployed.
2026-04-06 14:30:07 -07:00
7777dadcff docs: add deploy tests documentation to contributing guide (#92388)
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## What?

Adds documentation to the contributing guide explaining how deploy tests
work and how to run them.

## Why?

Deploy tests are an important part of the Next.js CI pipeline that
verify the framework works correctly when deployed to Vercel. However,
there was no documentation explaining:
- How deploy tests are triggered on PRs
- How to run deploy tests locally

This came up in a Slack discussion where team members were debugging
deploy test failures and sharing knowledge about how to trigger and run
these tests.

## How?

Added a new "Deploy Tests" section to `contributing/core/testing.md`
that explains:

1. **Triggering Deploy Tests on PRs**: Deploy tests don't run on every
PR by default. To trigger them, you can modify a test file in the deploy
test suite, which causes CI to run deploy tests for that file.

2. **Running Deploy Tests Locally**: You can run deploy tests locally
using:
- `NEXT_TEST_VERSION` to test against a specific commit's pre-built
tarball
- `NEXT_TEST_DEPLOY_URL` to skip the deploy step and test against an
existing deployment

<!-- NEXT_JS_LLM_PR -->
<!-- CURSOR_AGENT_PR_BODY_END -->

[Slack
Thread](https://vercel.slack.com/archives/C04KC8A53T7/p1775265710012189?thread_ts=1775265710.012189&cid=C04KC8A53T7)

<div><a
href="https://cursor.com/agents/bc-014a1052-4dfe-5db4-931d-86efa411016e"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-014a1052-4dfe-5db4-931d-86efa411016e"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

---------

Co-authored-by: Cursor Agent <[email protected]>
2026-04-05 14:58:02 -07:00
Zack TannerandGitHub d5f479c128 ci: remove deploy examples workflow from build-and-deploy (#92324)
We don't need to deploy a single image component example every time
`build_and_deploy` runs. If something about this example changes, it can
be manually re-deployed.
2026-04-03 15:10:06 -07:00
Zack TannerandGitHub 392d02ae8b ci: fix stats action (#92325)
We recently re-imaged the self-hosted Linux runners and it now hits
`ERR_PNPM_EXDEV` when pnpm copies packages between its default store and
the temp stats workspace. Keeping both under the same temp root avoids
the cross-filesystem copy failure.
2026-04-03 14:25:13 -07:00
Zack TannerandGitHub 9cb2048439 Ensure app-page reports stale ISR revalidation errors via onRequestError (#92282)
Note: the change is mostly whitespace. Recommend reviewing w/o
whitespace
[here](https://github.com/vercel/next.js/pull/92282/changes?w=1).

For App Router pages using time-based ISR, a stale cached response can
be returned before background revalidation finishes. If that background
revalidation later throws, the error does not bubble back through the
normal top-level `app-page` request catch. Instead, the response cache
has already resolved the request and later logs the failure internally.

When an error happens while rendering an app router page, and the entry
is stale, we now explicitly await `routeModule.onRequestError(...)`
before rethrowing.

This copies similar handling in pages router:
https://github.com/vercel/next.js/blob/daca04d09bf9aaee9e1c63324166985b643e9844/packages/next/src/server/route-modules/pages/pages-handler.ts#L438-L460

and route handlers:

https://github.com/vercel/next.js/blob/daca04d09bf9aaee9e1c63324166985b643e9844/packages/next/src/build/templates/app-route.ts#L407-L409
2026-04-03 09:04:29 -07:00
Zack TannerandGitHub c06658e919 fix: preserve HTTP access fallbacks during prerender recovery (#92231)
When a `notFound()`, `forbidden()`, or `unauthorized()` error escapes
into the outer prerender recovery path, we were falling back to the
generic error shell flow.

In the `cacheComponents` case, that could leave us with:
- error HTML rendered from `ErrorApp`
- Flight data reused from the aborted prerender prelude
- references to Flight chunks that were never emitted

That is what caused the client-side `Connection closed` failure in
#86251.

Instead of rerendering the full Flight tree or always using the generic
error RSC payload, this change:

- finds the deepest matching HTTP fallback boundary
- rerenders the normal app router payload with that segment-scoped
fallback
- tees the replacement Flight stream so Fizz can render from one copy
while prerender buffering consumes the other
- only takes this path for recoverable HTTP access fallbacks that have a
real boundary (ie a defined not-found/unauthorized/etc)

If no matching boundary exists, we keep the existing generic error
handling.

Fixes #86251
Fixes #90837
Closes #87041
Closes #86251

Closes NAR-711
Closes NEXT-4876
2026-04-02 07:54:11 -07:00
Zack TannerandGitHub c291479011 partial fallbacks: adapter support for intermediate shells (#91902)
Previously, `partialFallback` was only emitted when all dynamic params
could become fully concrete after upgrade. For a route like
`/prefix/[one]/[two]` where only `[one]` has generateStaticParams, the
feature was disabled entirely.

This relaxes the guard to allow adapters to produce an intermediate
shell for not fully known params, and tweaks the handling to support
when both known and unknown params are provided to the render.
Concretely:

- When partial `nxtP*` params are provided during background
revalidation but `normalizeDynamicRouteParams `rejects them (missing
params), merge the provided params into the existing params to override
placeholders.
- Compute `effectiveFallbackRouteParams` by filtering to only params
that still have placeholder values. Use this filtered set for
`fallbackRouteParams` so intermediate shells render resolved params in
the static shell and only suspend for truly unknown params
2026-04-01 09:49:59 -07:00
Zack TannerandGitHub 1e73fa94ac adapters: remove unused suffix code (#91997)
The regex associated with this flag was the same value in both the
true/false case and the underlying flag was only used to control this
regex. This appears to be dead code, so removing it.
2026-03-27 18:07:28 -07:00
56d75a0b77 Fix invalid HTML response for route-level RSC requests in deployment adapter (#91541)
In a deployed environment, `onCacheEntryV2` determines whether a
postponed response is HTML-origin or RSC-origin by checking whether
meta.url ends with `.rsc`.

For some dynamic full-route RSC requests, Next was passing a URL with
query params into onCacheEntry, for example:
`/[tenant]/samples.rsc?nxtPtenant=tenant-x`

Because that string does not end with .rsc, `onCacheEntryV2`
misclassified the request as HTML and treated it as text/html instead of
an RSC response.

This PR normalizes the URL before passing it to `onCacheEntry`, so the
callback receives the pathname rather than the full URL-with-query.

---------

Co-authored-by: JJ Kasper <[email protected]>
2026-03-18 12:17:31 -07:00
Zack TannerandGitHub a41bef94c5 improve allowedDevOrigins error (#91521)
This improves the blocked-request warning so it names the actual dev
resource being requested and gives clearer guidance on how to allow it.
When the source host is known, the message includes an inline
`allowedDevOrigins` config snippet; when the source is missing or
opaque, it explains why Next.js cannot infer a host to allow.
2026-03-17 17:35:29 -07:00
Zack TannerandGitHub b2b802c043 block disallowed dev origins by default (#91507)
This removes the warn-only default behavior and enforces the dev-origin guard by default. Cross-origin requests to internal dev resources now block unless they match the built-in local allowlist or an explicit `allowedDevOrigins` entry. The tests are expanded to cover default blocking, configured-but-not-allowlisted hosts, missing Referer in the no-cors path, and same-site requests without an Origin, and the docs are updated to match the new behavior.
2026-03-17 16:02:33 -07:00
Zack TannerandGitHub d0a0474d3d fix allowedDevOrigins for no-cors requests (#91506)
This PR makes configured `allowedDevOrigins` apply to cross-site no-cors dev asset requests. When browsers omit Origin for subresource loads, the dev guard now falls back to `Referer` so explicit allowlisted hosts can load `/_next/*` resources in development.

Previously, when `allowedDevOrigins` was configured, cross-site no-cors requests to internal Next.js dev resources were still blocked even for allowlisted hosts, because that code path never consulted the allowlist.
2026-03-17 13:57:40 -07:00
a27a11d78e Disallow Server Action submissions from privacy-sensitive contexts (#91478)
See:
https://github.com/vercel/next.js/security/advisories/GHSA-mq59-m269-xvcx
and [16.1.7](https://github.com/vercel/next.js/releases/tag/v16.1.7)

---------

Co-authored-by: Sebastian "Sebbie" Silbermann <[email protected]>
2026-03-16 18:57:51 -07:00
Zack TannerandGitHub 00bdb037af Patch improvements into http-proxy lib (#91480)
See:
https://github.com/vercel/next.js/security/advisories/GHSA-ggv3-7p47-pfv8
2026-03-16 18:41:16 -07:00
862f9b9bb4 Allow blocking cross-site dev-only websocket connections from privacy sensitive origins (#91479)
See:
https://github.com/vercel/next.js/security/advisories/GHSA-jcc7-9wpm-mj36
and [16.1.7](https://github.com/vercel/next.js/releases/tag/v16.1.7)

Co-authored-by: Sebastian "Sebbie" Silbermann <[email protected]>
2026-03-16 17:42:03 -07:00
Zack TannerandGitHub cd49df2d22 disable sub shell generation test outside of adapter (#91353)
These tests have started failing in deploy mode in environments outside
of the new Vercel adapter. Shell related behavior is changing as part of
the new `partialFallbacks` flag and will not be backported to the old
CLI, so this gates the test to ensure it runs in the right deployment
environment.
2026-03-14 03:22:06 +00:00
Zack TannerandGitHub ae3f9f5187 partial fallbacks: complete generic shells into more specific shells (#91231)
In #91158, I wired up the plumbing to indicate whether a partial
fallback shell is upgradeable. The previous heuristic was too coarse.
This wires up the handling in `next start`.

This PR teaches the runtime to complete a fallback shell only as far as
prerendering allows. Instead of promoting a generic shell like
`/[one]/[two]` directly to `/c/foo`, it promotes it to the most specific
prerendered shell for that branch, `/c/[two]`, where `[one]` has
`generateStaticParams`. That means later requests can reuse the more
complete shell, while fully dynamic params continue to stream as dynamic
content.

With this change:

- the first request still serves the generic fallback shell immediately
- the background revalidate writes a more specific shell, not a fully
concrete route
- later requests for the same prerendered branch reuse that shell
- upgrading stops once only fully dynamic params remain

This keeps the runtime behavior aligned with the build-time
`remainingPrerenderableParams` contract from the downstack PR.
2026-03-13 18:21:20 -07:00
Zack TannerandGitHub cf4d3ae89c partial fallbacks: only upgrade shells with remaining prerenderable params (#91158)
Partial fallback upgrading is currently too broad. Any PPR fallback shell can be treated as upgradeable, including routes with no `generateStaticParams` and shells that are already as specific as prerendering can make them.

In practice, that means we preserve `allowQuery` and enable background promotion for shells that should remain as partial fallbacks. That broadens the feature beyond the medium-cardinality case it was meant for and makes the build output imply per-param upgradeability when there are no prerenderable params left to fill.

This PR teaches static-path generation to compute `remainingPrerenderableParams` for each fallback shell: the unresolved pathname params that can still be filled by `generateStaticParams` in that branch. We then use that signal to gate partial fallback behavior.

With this change:

- `partialFallback` is only emitted for shells that still have prerenderable params remaining
- `allowQuery` with params is only preserved for those shells

Effectively, this limits partial fallback upgrading to shells that can still be made more specific by prerendering.
2026-03-13 17:35:14 -07:00
Zack TannerandGitHub afe3993eb9 re-enable RDC deployment tests (#91327)
Flag has been re-enabled and is attached to the test team.
2026-03-13 11:19:43 -07:00
Zack TannerandGitHub 5ef117cdf3 Revert "Exclude partial fallback for deploy mode" (#91172)
Reverts vercel/next.js#91163

Flag is re-landed for test teams
2026-03-12 10:56:07 -07:00
Zack TannerandGitHub 4e2353edb2 fix: app-page URL normalization (#91121)
## Summary

Fix an App Router request normalization gap where app-page route-module
requests could keep internal RSC/segment-prefetch URLs in `req.url`.

This could leak paths like:

- `.../.segments/_tree.segment.rsc`
- `.../__PAGE__.segment.rsc`

into App Router render state and surface through `usePathname()` during
server rendering.

## What changed

- Normalize `req.url` in the app-page route-module path after `.rsc` and
`.segments/*.segment.rsc` pathname normalization.

## Why

`base-server` already keeps `req.url` in sync after RSC normalization
([ref](https://github.com/vercel/next.js/blob/5e11e67759fa38fe67f70790d7bba8c9ff9ba5fd/packages/next/src/server/base-server.ts#L676-L680)),
but the app-page route-module path only updated `parsedUrl.pathname`.

Since App Router render state seeds its canonical URL from `req.url`,
that desync could cause internal segment-prefetch paths to be treated as
the current pathname.
2026-03-09 16:01:35 -07:00
Zack TannerandGitHub c0bf4b6f00 partial fallbacks: gate behind experimental flag (#91123)
This puts the partial fallback upgrading feature introduced in
https://github.com/vercel/next.js/pull/89063 behind a flag to make it
easier to test the rollout/eventual stabilization in isolation.
2026-03-09 15:58:25 -07:00
Zack TannerandGitHub af48a18368 re-introduce partial fallback -> route upgrading (#89063)
In https://github.com/vercel/next.js/pull/69282, we landed support for
Partial Fallback Prerendering. The intention behind this feature was to
be able to upgrade from a partial fallback (essentially the UI produced
when `await params` is dynamic, ie the param was not part of
`generateStaticParams` at build time) to a route shell (when the param
values are filled in, and thus we can prerender more of the page).

It was reverted in https://github.com/vercel/next.js/pull/79258 because
we didn't add first-class support to this in the build output API and
the necessary infrastructure changes to perform similar behavior that
this PR does to trigger a background revalidation with params filled in.

This re-lands the feature in Next.js now that upstream support landed
(https://github.com/vercel/vercel/pull/14703,
https://github.com/vercel/vercel/pull/15338, and Vercel infra changes
which are rolling out)
2026-03-06 08:53:43 -08:00
Zack TannerandGitHub cb54d203ea preserve allowQuery for partial fallback shells (#90887)
Analogous change to https://github.com/vercel/vercel/pull/15338, but for the new Next.js adapter API.

This updates only allowQuery for fallback HTML when the route is a true partialFallback (PPR fallback with postponed state) and cache components is enabled. For all other fallback cases, behavior stays the same as today (allowQuery is cleared to [] for shared fallback caching).

This change is needed because partial-fallback shells can be param-specific, so collapsing them to one shared fallback cache key can serve the wrong shell across params and block correct upgrade behavior. Gating this behind partialFallback lets us roll out the new behavior safely and independently, without changing legacy fallback semantics for non-partial paths.
2026-03-06 08:16:40 -08:00
Zack TannerandGitHub 1c9577e3de partial fallbacks: add adapter flag (#90395)
Plumbs the new `partialFallback` through `onBuildComplete`, which is
consumed by `adapter-vercel` to signal that a prerender is a partial
fallback (PR forthcoming, once this lands, so it's available on the
types). For more information on what a partial fallback is, see the
downstack PR.
2026-03-04 13:22:20 -08:00
Zack TannerandGitHub 9ff3b7c424 [ci]: continue-on-error for more gh auth status checks (#90890)
This seems to be failing for our deploy test workflow
([x-ref](https://github.com/vercel/next.js/actions/runs/22685809647/job/65778800145)).

Updating to `continue-on-error` similar to
https://github.com/vercel/next.js/pull/89098 because this check doesn't
seem reliable.

If it fixes, will just remove in both spots all together.
2026-03-04 13:17:19 -08:00
Zack TannerandGitHub bbb72bf258 enable server action RDC deploy test (#90796)
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->
2026-03-02 18:28:43 -08:00
Zack TannerandGitHub fd38d5bf15 segment cache: add test for passing unawaited promise to context provider (#89339)
Adds a failing test proving that if the RSC response from a prefetch
contains an unresolved promise, navigating to the page will cause the
Suspense boundary wrapping the use of that promise to remain in fallback
state indefinitely.

This appears to have regressed in
e9a03ac12c, though the theory is that this
is just uncovering a React bug rather than causing the issue.

Closes #89170
2026-02-21 10:29:09 -08:00
Zack TannerandGitHub f33b8af469 Revert "Handle null history.state in client-side router popstate handler" (#90268)
Reverts vercel/next.js#90083

This causes an MPA navigation when updating the hash fragment via
`window.location.hash = "foo"`
2026-02-20 22:04:52 +00:00
Zack TannerandGitHub 633edeb54f [ci]: pin styled-components version in tests (#90194)
The latest version is causing deploy test failures. 

x-ref:
https://github.com/styled-components/styled-components/issues/5667
x-ref:
https://github.com/vercel/next.js/actions/runs/22162110706/job/64084432174#step:34:375
2026-02-19 08:08:45 -08:00
Zack TannerandGitHub da445e89cd fix: normalize loopback only in hostname (#90158)
`NextURL` intentionally canonicalizes loopback hosts (127.x.x.x, [::1],
localhost) to localhost so that internal URL handling is consistent
across equivalent local origins.

However, we were applying a regex replacement to the entire URL before
parsing, which unintentionally rewrote loopback strings inside query
parameter values, eg `?redirect_uri=http%3A%2F%2F127.0.0.1...`. This is
unexpected for anyone that is explicitly passing through different
loopback values.

This fixes it by first parsing the URL with `new URL()`, and then only
apply the replacement logic to `parsed.hostname` when it is a loopback
host. This leaves search unchanged.

Fixes NEXT-4864
2026-02-18 11:54:24 -08:00
Zack TannerandGitHub c885d4825f ensure maxPostponedStateSize is always respected (#90060)
`maxPostponedStateSize` should be verified in all cases where the
postponed body is buffered. This fixes a branch in self-hosted setups
where that check was missing.
2026-02-18 08:53:21 -08:00
Zack TannerandGitHub 4f5da82080 segment cache: fix segment cache normalizer (#90111)
This fixes an issue where deploying an app that explicitly named a
catch-all segments as `[...segments]` or `[[...segments]]` would lead to
repeated ISR cache misses on that route, even if it was generated at
build time.

This is because the normalizer that is responsible for extracting the
segment path wasn't escaping the `.segments` directory value, so the `.`
was treated as a wildcard. That meant when the server attempted to look
up the underlying segment data, it wouldn't find it and would have
responded with a 204, which signals to the upstream CDN that it is not a
cacheable response.

Fixes #87090
2026-02-17 22:35:40 -08:00
Zack TannerandGitHub b0ebf2a822 fix: fully static pages should emit & serve static rsc payloads (#89202)
This restores fast navigations to fully static PPR routes in Cache
Components, even when prefetch hasn’t completed or `prefetch={false}` is
used. In legacy versions of PPR, the `prefetchDataRoute` entries would
be populated with `.prefetch.rsc` values containing static RSC payloads.
This regressed in cache components, and the only static RSC payloads
were in the `.segments` directory. However, when Next.js triggers a
regular RSC request (non-prefetch), either because the prefetch hadn't
completed yet or `prefetch={false}` was configured, we'd route to the
empty fallback and trigger a function invocation.

This restores old behavior of emitting a `.rsc` file for a fully static
route. This information technically also exists in the `.segments`
directory, but it's split into parts, and it's now routed to unless
explicitly done so via the `next-router-segment-prefetch` header. In
addition to emitting the route, this also ensures we set
`prefetchDataRoute` to point to this. This is how the Vercel adapter
knows the file to serve.

An e2e regression test now asserts that `prefetch={false}` navigation
does not wait for a dynamic render. The deploy test will be unblocked
once https://github.com/vercel/vercel/pull/14770 lands.
2026-01-29 14:26:40 -08:00
Zack TannerandGitHub d5a88ba4eb tweak LRU sentinel cache key (#89123)
We originally prefixed the TTL sentinel with the null-byte separator to
avoid collisions with real invocation IDs, but that makes
`extractInvocationID` return "ttl" instead of undefined for TTL-mode
keys.

This switches to a reserved magic string sentinel so TTL-mode entries
are correctly treated as “no invocation ID”.
2026-01-27 20:26:59 +00:00
Zack TannerandGitHub c986bcccf1 fix: preserve cache behavior for PPR fallback shells with root params (#88556)
When generating PPR fallback shells, a cache miss during warmup was
being treated as a dynamic hole, so the warmup render never filled new
cache entries. This caused root‑param fallback shells (e.g.
`/en/blog/[slug]`) to suspend even though root params were already
known.

This change always creates a fresh prerender RDC for warmup and copies
any seed hits into it. The final render then uses the warmed cache, so
fallback shells can reuse populated entries without short‑circuiting. On
the export side, we now choose a seed RDC by matching known params (e.g.
locale) so /en/... fallback shells don’t get seeded with /fr/... data.
(Previously, the RDC seed was "last-write-wins".

Fixes NAR-716
2026-01-21 08:45:07 -08:00
Zack TannerandGitHub 6138452203 [test]: add ability to run test-deploy with pre-existing deployment (#88829)
When digging into failing deployment tests, I often will re-run the test
itself without wanting to change anything about Next.js or the test
application, especially when I suspect a logic bug in the test itself or
need to figure out what's causing a flake.

This adds an environment variable that can be used to skip the
build/deploy step and will use an existing deployment URL to run the
tests against.

I suggest reviewing this [without
whitespace](https://github.com/vercel/next.js/pull/88829/changes?w=1).
2026-01-20 14:40:49 -08:00
Zack TannerandGitHub c1a752bcca Revert "prevent browser cache from using stale RSC responses from pre… (#88457)
…vious builds (#86554)"

This reverts commit 3bbb2e61d5.

Need to investigate some upstream constraints before we land this in a
stable release.
2026-01-12 17:54:57 -08:00
Zack TannerandGitHub 90a4927806 fix: use RDC for server action requests (#88129)
When a server action triggers a re-render of the underlying page (eg by
calling `refresh()`), cached data that was part of the Resume Data Cache
(RDC) was not provided to the server action handler, and so those parts
of the UI would update with new data. A subsequent refresh of the page
would revert back to the ISR data, which means the server action causes
the data to temporarily get into an "ahead" state that will never
actually be reflected in the ISR shell.

This provides the RDC data to the server action handler. For self-hosted
deployments, Next.js can look up the cached entry directly since the
cache and renderer are co-located. For deployments on Vercel, the
caching layer and rendering layer are separate services, and server
actions bypass the cache. This means the serverless function has no way
to access the cached RDC on its own, so the underlying CDN must fetch it
and pass it via the request body. The `x-next-resume-state-length` is
sent to the serverless function so that it can determine how to split
off the RDC data from the action body.

Fixes NAR-478
Fixes NAR-502
2026-01-12 09:17:44 -08:00
Zack TannerandGitHub 0d4649989d next/image: support custom cache handlers (#88248)
When self-hosting Next.js, it's possible to customize a cache handler
for ISR. Self-hosted Next.js also makes use of a similar cache interface
for `next/image`, but there's no way to customize this cache handler.

This plugs into the [existing
ability](https://nextjs.org/docs/app/api-reference/config/next-config-js/incrementalCacheHandlerPath)
to customize a `cacheHandler` to support the `IMAGE` type. This lets you
implement whatever constraints you might have on your self-hosted
environment, eg the need for an LRU cache, or storing optimized images
outside of disk.

This is currently opt-in because it's a breaking change for cache
handlers to start receiving `IMAGE` cache types, which we'll make
default in the next major.
2026-01-08 10:58:49 -08:00
Zack TannerandGitHub d044c5542e ci: fix javascript-urls test to account for React 18 (#88249)
This was caught by our React 18 tests which only run on `canary`. There
was a console error about breaking `javascript:` urls in an upcoming
React release but it didn't actually block them.
2026-01-07 16:27:04 -08:00
Zack TannerandGitHub b1ce6042be add compilation error for taint when not enabled (#88173)
Using `taint` APIs from React without enabling `experimental.taint` will
error at runtime because it needs to bundle experimental React, making
it hard to catch and potentially leading to downtime. This updates our
transform to throw an error if we detect that it's imported but `taint`
isn't enabled.

Fixes NAR-690
2026-01-06 11:57:46 -08:00
Zack TannerandGitHub 3bbb2e61d5 prevent browser cache from using stale RSC responses from previous builds (#86554)
When we landed #76207 we started propagating the
`stale-while-revalidate` value to RSC responses. We wanted a way to
express to CDNs that it can keep serving the cached content for some
time while a revalidation runs in the background, but we specifically
don't want that for private caches.

As a result of this header, when re-building your application locally
(or doing something on the server that would have expired the cache),
the browser's disk cache would serve a stale RSC response. We currently
encode a buildId in RSC payloads, so the client router will discard RSC
responses that don't match what it is expecting.

Unfortunately there isn't a `s-stale-while-revalidate` header to express
the intended semantics. This moves the `stale-while-revalidate`
configuration into the `CDN-Cache-Control` header, which is becoming
standardized and is supported by a wide variety of CDNs. This allows us
to specify the SWR behavior more explicitly to CDNs while not impacting
private caches like the browser. It restores the previous behavior of
only setting `s-maxage` on the `cache-control` itself to avoid
influencing browser cache.

If Next.js is deployed to a CDN that doesn't support this header, it can
be customized via `nextConfig.experimental.cdnCacheControlHeader`. Eg,
if deployed to Fastly, you'd configure this to `cdnCacheControlHeader:
'Surrogate-Control'`.

Closes NAR-525

Reference docs:


[Vercel](https://vercel.com/docs/headers/cache-control-headers#cdn-cache-control-header)

[Cloudflare](https://developers.cloudflare.com/cache/concepts/cdn-cache-control/)

[Fastly](https://www.fastly.com/documentation/reference/http/http-headers/Surrogate-Control/)

[RFC 9213](https://httpwg.org/specs/rfc9213.html)
2026-01-05 12:17:57 -08:00
Zack TannerandGitHub 100253c450 ci: track runner name on datadog test reports (#87440)
So we can see if there are any outliers where a particular runner is
failing tests more often than others.
2025-12-19 15:59:26 -08:00
Zack TannerandGitHub c95eb899fa test: de-flake client-cache deployment tests (#87412)
These tests aren't resilient to changes in router behavior after
extensive refactors. What looks to be happening is a race between the
prefetch being issued and the click firing:
1. Cache expires -> refetch prefetch is triggered
2. Click happens while prefetch is in-flight -> route entry is Pending
3. Since no fulfilled cache entry exists, `navigate()` falls through to
`navigateDynamicallyWithNoPrefetch()`
4. This issues a full dynamic request
5. The full dynamic response is favored and skips the loading state

This ensures that we are waiting for network activity to finish before
navigating.
2025-12-19 11:08:10 -08:00
Zack TannerandGitHub 8a8a00d5d0 Revert "Move next-env.d.ts to dist dir" (#87311)
Reverts vercel/next.js#86752

This has consequences when `.next` is in `exclude`. Reverting for now.
2025-12-18 16:00:13 +00:00
Zack TannerandGitHub ca831cfccc test: fix actions deployment tests (#87279)
Fixes a few failing deployment tests that weren't validated when landed
last week.

- next.cliOutput is not available when deployed because it's part of
runtime logs
- status code changes on Vercel because POSTing to a static 404 page is
treated differently.
2025-12-17 10:17:22 -08:00
Zack TannerandGitHub 4f13405be7 fix: otel error spans from streamed responses (#86955)
When an error is thrown inside a Suspense boundary during streaming SSR,
the error was not being captured in the "render route (app)" span. This
happened because `getTracer().wrap()` ends the span as soon as the
stream is created and returned, but errors inside Suspense boundaries
occur asynchronously during stream consumption.

This PR changes the span management from using `wrap()` to manually
calling `startSpan()` and tracking the span lifecycle. The span now
stays open until `allReady` resolves or rejects. A new `withSpan()`
helper was added to the tracer to properly activate the span context so
child spans are parented. Error handlers now accept an optional
`spanToRecordOn` parameter to record exceptions on the correct span
rather than relying solely on the active scope span.

Fixes #86517
2025-12-15 13:31:31 -08:00
Zack TannerandGitHub 32f6ed396e improve segment cache lru typesafety (#87129)
The LRU and cache map code was using any types in several places
`(MapEntry<any>`,` type LRUNode = MapEntry<any>`) which meant we had no
type safety for those operations. This masked a bug fixed in #87124
where `deleteFromCacheMap(tail.value)` was being called incorrectly -
the `any` typing let it compile when it shouldn't have.

This PR introduces a `LRUNode` type that captures the structure needed
for heterogeneous LRU operations (since the LRU holds both
`RouteCacheEntry` and `SegmentCacheEntry`). The generic `MapEntry<V>` is
kept for type-safe map operations, while `LRUNode` is used for deletion
and LRU logic.
2025-12-12 17:04:02 -08:00
d43d57afd0 Remove urlencoded action handling & harden action ID checks (#87082)
- Removes support for urlencoded actions
- Errors when a server action request is received in apps that have no
server actions
- validate action ID in MPA actions before proceeding

---------

Co-authored-by: Josh Story <[email protected]>
2025-12-11 13:56:15 -08:00
Zack TannerandGitHub a315d9fe32 Revert "add bundle analyzer as dev dependency to next (#86497)" (#86672)
I believe this is still breaking publishes. Reverts #86497
x-ref:
https://github.com/vercel/next.js/actions/runs/19790732218/job/56728905106
2025-11-30 20:23:23 +00:00
Zack TannerandGitHub d7e17617a2 add debug logs to onSegmentPrerenderError (#86358)
Adds logs to collectSegmentError when verbose logging is enabled to help
identify errors that occur during this phase.
2025-11-21 12:24:33 -08:00
Zack TannerandGitHub 09c2f3c992 Revert "Turbopack: add bundle-analyzer to versioning and add dependen… (#86394)
…cy (#86355)"

This reverts commit 5b97f1f7b5.

Investigating if it fixes broken publishes.
2025-11-21 11:40:13 -08:00
Zack TannerandGitHub 06d45e7de8 fix: prevent fetch abort errors propagating to user error boundaries (#86277)
When navigating away from a page due to an MPA navigation or browser
refresh, we were aborting any pending RSC requests. However, in the case
where the abort was due to an MPA navigation, the browser would restore
the execution context via the built-in bfcache, and the aborted fetch
would cause React to get in an errored state, leading to
"BodyStreamBuffer was aborted".

Rather than aborting the pending requests, we instead mark that we would
have aborted due to the page unloading. That still solves the original
reason the flag was added (suppressing the fetch errors that get logged)

Fixes NAR-519
2025-11-19 07:31:44 -08:00
Zack TannerandGitHub bf27e24aca fix: cacheMaxMemorySize should not disable dev HMR cache (#86164)
When configuring `cacheMaxMemorySize` to disable memory caching
(typically used for setups to adjust production caching behavior,
especially in multi-process self-hosted setups), this inadvertently also
disabled dev HMR caches which are intended as a performance
optimization. As a result of this, the dev console would be spammed with
"Single item size exceeds maxsize".

It's still possible to use this configuration to set a larger cache, but
otherwise it will have a minimum set to the previous default.

Fixes NAR-463
x-ref:
https://github.com/vercel/next.js/pull/85153#issuecomment-3429636751
2025-11-15 11:25:47 -08:00
Zack TannerandGitHub c6a4c3b39e update routes-manifest to include whether app has pages routes (#86051)
The Vercel CLI produces a lot of `/_next/data` routes regardless of if
pages router is in-use. There's a lot of different metadata we emit but
nothing concretely tells us if an app has pages router enabled. For app
router, we rely on the presence of `app-paths-manifest`, but in pages
router, we always emit a `pages-manifest`.

Rather than trying to cobble together something in the CLI, this updates
the routes manifest to explicitly output the app type (pages, app, or
hybrid).
2025-11-12 12:52:34 -08:00
Zack TannerandGitHub 26b95c3f0f [ci]: fix retry_deploy_test workflow (#85981)
When we fixed deploy tests to consistently run with the explicitly
provided Next.js release version, it broke this job which was relying on
an explicit match on the "test e2e deploy canary" string.
2025-11-12 11:31:27 -08:00
Zack TannerandGitHub 7fea7876b2 switch to slice in createRuntimePrefetchTransformStream (#85822)
It's safer to copy here than to pass a reference, because it's possible
that the underlying chunk became detached. Accidentally tweaked this
before landing #85595
2025-11-10 11:27:34 -08:00
f7d262902a fix isDynamicRSC condition when deployed (#85919)
Next.js relies on on the Resume Data Cache to prevent tearing between
the statically prefetchable parts of the UI by seeding the resume with
the same cache as the revalidation/build. The RDC data is stashed in the
postponed state which is attached to all of the different outputs that
comprise a page (the segments, the HTML, and the dynamic RSC data).

However, when deployed to targets like Vercel, the revalidation was
incorrectly bypassing the cache for the RSC entry, because it thought
that it was a resume. This led to a drift in cached values, because the
revalidation would cause the main RSC entries RDC data to contain a
different value than what was used for the segment prefetches & HTML ISR
entry.

Fixes NAR-493

Co-authored-by: JJ Kasper <[email protected]>
2025-11-07 17:34:46 -08:00
2f86fbab81 [runtime prefetching]: fix runtime prefetching when deployed (#85595)
Runtime prefetching relies on the presence of headers to determine
caching behavior: `x-nextjs-postponed` indicates if the response was
partial (so it knows if it should trigger a dynamic request to retrieve
the missing data), and `x-nextjs-stale-time` provided stale time
information to the client router. This worked fine in `next start` but
due to how this is modeled in our Vercel deployment adapter, it was not
possible to set runtime headers after the initial headers have been
sent, as these requests were routed to prerenders.

As a result of this limitation, this moves both the isPartial flag and
the stale time value into the payload body. The response is run through
a transform stream that replaces a sentinel value (`"rp": [sentinel]`)
with the final stale time/isPartial values after we determine them. This
avoids regenerating the entire RSC payload while ensuring correct values
are sent to the client. Both properties are only included in runtime
prefetch responses.

Closes NAR-494

---------

Co-authored-by: Josh Story <[email protected]>
2025-11-04 18:44:59 -08:00
Zack TannerandGitHub 575c8a7dcf remove unused RSC payload property (#85746)
This property is from back when we forked client router handling based
off the presence of the `postponed` payload, but it's no longer being
read by anything, so this PR removes it.
2025-11-04 15:34:26 -08:00
Zack TannerandGitHub 05d7111090 [test]: move resume-data-cache to e2e test (#85647)
Moves `resume-data-cache` to `test/e2e`. We don't currently run
`production` tests when deployed - many of them do funky things with
`next.build` / `next.start` and are meant to test local behavior rather
than deployed behavior.

As a result, I also temporarily disabled this test when deployed because
there are currently bugs.
2025-10-31 16:17:57 -07:00
Zack TannerandGitHub 567dc18b23 move segment cache entries to top level segment-cache dir (#85542)
This removes the indirection that was set up to codesplit on the client.
But now that there's only a single client cache entrypoint, we can
delete the indirection and move everything to a top-level export.
2025-10-31 15:37:24 -07:00
Zack TannerandGitHub d349bd0894 [test]: fix broken scroll restoration test (#85599) 2025-10-31 10:22:16 +01:00
Zack TannerandGitHub 2f052b16f6 fully remove clientSegmentCache flag (#85541)
Turning this flag off would have already caused client-side invariants
because we deleted all the old codepaths. This fully removes the
remaining plumbing that supported the flag.
2025-10-30 19:49:05 -07:00
Zack TannerandGitHub 1bca3db0bf fix: redirect should always return updated router state (#85533)
When a server action triggers a redirect, it will return the RSC payload
for the destination state in a single roundtrip. This lets us update the
UI without needing to waterfall when getting the target page's data. We
reject the server action with a special error signaling that the form
state should be reset, but otherwise the redirect itself is unnecessary,
since we already are handling it in the server action reducer.

However, when we introduced Activity for bfCache, this meant navigating
back to the previous page would replay the redirect error that was
stashed in the `RedirectBoundary`. I incorrectly patched this by just
returning the current router state, rather than the redirect
destination's state, but this lost the ability to return the updated
state in the same roundtrip as the redirect. Instead, this marks the
error that gets stashed in the `RedirectBoundary` as being "handled".
Re-activating the hidden subtree will now still correctly reset the
state (because the boundary handles it), but won't attempt to perform
the redirect again.

Closes NAR-470
2025-10-29 16:02:16 -07:00
Zack TannerandGitHub d35c7366b8 fix: staleTimes.static should consistently enforce a 30s minimum (#85479)
When the tree response sends back a static staleTime, we had handling to
ensure that it was at minimum 30s, because anything less would mean we'd
be discarding static cache entries more frequently than necessary.
Currently a value of 0 would result in a prefetch ping loop, because the
cache value would be immediately invalidated.

This updates our config validation to warn about values lower than 30s
and ensures the `getStaleTimeMs` function applies to the value read from
env, too.
2025-10-28 16:51:25 -07:00
Zack TannerandGitHub b55e52f1bd docs: remove inaccuracies from use cache: private (#85425)
There are a lot of things in here that aren't quite fully fleshed out
yet (eg runtime prefetching) as well as some inaccuracies (eg `use
cache: private` is not required for runtime prefetching, it's just
another thing that _can_ be runtime prefetched).

This trims the doc down until we can focus on proper guidance.
2025-10-27 17:22:33 -07:00
Zack TannerandGitHub 5e282808c0 remove unstable_forceStale prefetch option & restore prefetch={true} functionality (#85411)
`prefetch={true}` with `cacheComponents` was opting into runtime
prefetching, with `unstable_forceStale` preserving the old behavior of
fetching the full (stale) data. However we only intended to expose
runtime prefetching via the `export const prefetch` segment config.

This removes `unstable_forceStale` and restores previous
`prefetch={true}` behavior. I've disabled some of the tests that were
relying on the old link behavior for opting into runtime prefetching -
we'll need to refactor those to use the segment opt-in or just remove
them all together.

Fixes #85162 
Closes NAR-320
2025-10-27 12:59:45 -07:00
Zack TannerandGitHub 47ceda3c14 [cache components] persist cache bypass UI until it's disabled (#85190)
Previously we were only showing this during navigations when caches are
bypassed. We want to make it clearer that you are in this state and dev
might not work as intended while caches are disabled.

This will show the cache bypass status on initial load and will reset
the next time a router action occurs that doesn't bypass cache.


https://github.com/user-attachments/assets/f82a98c6-b5be-44d0-ba86-e4f7ca7010e4
2025-10-21 16:04:48 -07:00
Zack TannerandGitHub b66c1d6176 Remove layout-router sticky/fixed debug warning (#85193)
Fixes an issue that reproduces due to a combination of the log
forwarding logic alongside logging out an explicit element. We can add
this back in the future once our log forwarding library properly ignores
non-enumerable properties.
2025-10-21 16:04:25 -07:00
Zack TannerandGitHub da024c190a [cache components] move experimental.cacheHandlers out of experimental (#85157)
Moves this flag out of experimental so that custom `use cache` handlers
can be configured alongside the cache components release.
2025-10-21 10:41:28 -07:00
Zack TannerandGitHub 149f18e83f enable experimental.routerBfCache behind cacheComponents (#84923)
This removes the `routerBfCache` and enables it automatically when
`cacheComponents` is enabled. This leverages `React.Activity` on layout
segments to support restoring previously visited UI segments while
preserving state.
2025-10-21 01:11:37 -07:00
Zack TannerandGitHub 3e10a73f68 guard navigation use hooks for React 18 (#85151)
We need to guard these calls, otherwise they fail in our React 18.3.1
tests. x-ref:
https://github.com/vercel/next.js/actions/runs/18671327784/job/53236002824
2025-10-20 21:56:42 -07:00