Skip to content

🔄 Sync from upstream - 2026-01-08#133

Merged
lakshit-hivel merged 60 commits intocanaryfrom
sync-upstream-20260108-064721
Jan 8, 2026
Merged

🔄 Sync from upstream - 2026-01-08#133
lakshit-hivel merged 60 commits intocanaryfrom
sync-upstream-20260108-064721

Conversation

@lakshit-hivel
Copy link
Copy Markdown

🔄 Upstream Sync

This PR syncs the latest changes from the upstream repository.

Changes: 60 new commit(s) from upstream

Recent Upstream Commits:

b933d3dc3a Turbopack: Remove tokio and turbo-task handles from Invalidator (#88242)
d044c5542e ci: fix javascript-urls test to account for React 18 (#88249)
d99021e9a2 v16.1.1-canary.17
8cf1d1f1fa Upgrade to swc 54 (#88207)
69d9d2909c Disallow javascript urls in router methods and redirects (#88185)
64c08f42a7 feat(turbo-tasks-fs): support multi denied_paths (#88186)
c0d6a5d81e Guard against Object/Array shadowing in 'use cache' transform (#88229)
053c67065e Turbopack: get rid of some manual sel

This PR was automatically created by the multi-repo orchestrator.
Repository: next.js
Timestamp: 2026-01-08T06:47:25.942841

nextjs-bot and others added 30 commits January 3, 2026 23:22
…idation (vercel#88069)

## Summary

Fixes a bug where calling `revalidateTag(tag, profile)` incorrectly
triggers client-side cache invalidation, causing read-your-own-writes
behavior that violates stale-while-revalidate semantics.

### The Problem

When `revalidateTag('tag', 'max')` is called in a server action:
1. The tag is correctly marked for stale-while-revalidate
2. BUT the `x-action-revalidated` header is incorrectly set to `1`
3. This triggers client-side cache invalidation via
`revalidateEntireCache()`
4. The client navigates and may display stale data from background
revalidation

This caused the confusing behavior where:
- Click 1: Nothing happens (correct)
- Click 2: Nothing happens (correct) 
- Click 3: Data changes to a stale value from click 1 (incorrect!)

### The Fix

In `addRevalidationHeader`, change the `isTagRevalidated` calculation to
only count tags **without** a profile (from `updateTag`). Tags with a
profile (from `revalidateTag`) should follow stale-while-revalidate
semantics and not trigger immediate client-side cache invalidation.

```typescript
// Before:
const isTagRevalidated = workStore.pendingRevalidatedTags?.length ? 1 : 0

// After:
const isTagRevalidated = workStore.pendingRevalidatedTags?.some(
  (item) => item.profile === undefined
) ? 1 : 0
```

### Expected Behavior After Fix

| API | Profile | Header Set | Client Behavior |
|-----|---------|------------|-----------------|
| `updateTag(tag)` | `undefined` | ✅ Yes | Immediate refresh
(read-your-own-writes) |
| `revalidateTag(tag, 'max')` | `'max'` | ❌ No | Keep stale data (SWR) |
| `revalidateTag(tag, { expire: 0 })` | `{ expire: 0 }` | ✅ Yes* |
Immediate refresh |

*For immediate expiration via `pathWasRevalidated` which is already
handled correctly.

## Test Plan

- [x] Added new test page at
`test/e2e/app-dir/use-cache/app/(partially-static)/revalidate-tag-no-refresh/page.tsx`
- [x] Added test case that verifies 3 clicks of `revalidateTag` with
profile don't change the displayed value
- [x] Verified existing `updateTag` test (`should update after
revalidateTag correctly`) still passes
- [x] Verified both tests pass with `pnpm test-start`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
i got bit by this often :p 

<!-- 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 #

-->
…cel#87988)

- redesigns the default global + default error boundaries. removing the
WSOD forever :/
- adds dark mode support
- unifies a bit of the styling
- add the digest for the server error
- adds a return button on the client errors

<img width="3328" height="1914" alt="CleanShot 2026-01-02 at 09 46
36@2x"
src="https://github.com/user-attachments/assets/9994eb37-c22b-4847-9a18-e9acf0ae6236"
/>

<img width="2144" height="1242" alt="CleanShot 2026-01-02 at 09 47
01@2x"
src="https://github.com/user-attachments/assets/9b3bcf39-63f6-4c8d-85c5-2976c25f5b7b"
/>


<img width="2238" height="1632" alt="CleanShot 2026-01-02 at 09 47
17@2x"
src="https://github.com/user-attachments/assets/436433d7-9873-496a-9c96-536e070be9d7"
/>
<img width="1708" height="1260" alt="CleanShot 2026-01-02 at 09 47
23@2x"
src="https://github.com/user-attachments/assets/1ec42402-dbd9-41a3-801b-4745a4f128f7"
/>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
adding basic config with graphite/repo instructions

<!-- 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 #

-->
)

## Summary

Reduces flakiness in the OpenTelemetry e2e test
(`test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts`) for
production mode.

### Root Cause
In production mode, Next.js generates additional spans from:
- RSC prefetch requests (with `?_rsc` query param)
- Edge runtime boundary spans

These extra root spans cause `toMatchObject` assertions to fail because
they receive more spans than expected.

### Changes

1. **Filter spans by expected `http.target`** in `expectTrace()`:
   - Extract expected `http.target` values from the match object
   - Filter root spans to only include those with matching targets
- This excludes RSC prefetch and edge boundary spans that aren't part of
the test assertion

2. **Fix TestExporter callback bug** in `instrumentation-test.ts`:
   - The success callback was called unconditionally (even after errors)
   - Added early `return` after error callback
   - Moved success callback inside the success path

## Test Plan
- [x] All 34 tests pass in production mode (`NEXT_TEST_MODE=start`)
- [ ] CI passes
…ilds (vercel#86554)

When we landed vercel#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)
Ensure that turbopack produces sourcemaps with the `names` field populated.

SWC has support for this but because we are using lower level APIs we need to collect identifiers ourself.  This follows the pattern that SWC uses internally in APIs like `Compiler::optimize`.

Partially addresses vercel#87896, to actually use these when reporting errors we need to modify the deobfuscation logic in next.


<!-- 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 #

-->
### What?

It's a VecDeque and we are calling pop_front() so we don't want to reverse the roots
This automatically transpiles this code with the browserslist config, since it's in the runtime as opposed to a generated snippet

[swc minifies this to the same output](https://play.swc.rs/?version=1.15.8&code=H4sIAAAAAAAAA919bVfcRrLwd35Fh%2BTcmbEHDTix14GLWYzxLolt%2FABe7z0sy2hGPSAzI00kDZh1%2BO9PvXS3ulutAecme%2FZczm4MUr9UV1fXe5e6F9N8FE9PLtMyOvlw9PLw%2Fe7ez%2BLXX0U3%2BGJbnJ71etF8UV52T1cE%2FFS3c5lPRJKPFzOZVWJ7e1us5qNPclytih3zPBovigL%2BPR4X6bwSm2KRJXKSZjLp0zBfVvPqUhZ7l4vsqlzdPF0tq7hKx4MxPRg8H41%2B%2FH70pyejZGP9h6fjUfSpXO17bZ7%2BON54%2BnQUP30%2BSZJkfRxq8%2Bzp8ySO%2F7Qx3vgxfh4%2FnWCbs%2F5qsciqdCbf5sliKg8SAuB0XuS4irPBPB5fxReyHGTyczVI0rIajKcpLGYQz%2Bdr%2BHCtWhSjHNvBgOIUH3OLM9GV41lc0qp7q2d3K2e9rZVutye2X4gvK%2BlEdL%2FZLYr4NkpL%2BjeI9l4P2iKWCgkTZVsrdysr4zwrK7H31w%2Fvfj5%2FuXu8f%2F5%2B9%2BSvsD%2Brg3MCc3VLNTnaf7N7cvC3%2FfOjw8OTuhX%2BVbf58O7k4C2M8eHlm4O91qF4tuMPr18f%2FB3eX8iK9ut4MZmkn18X%2BYx397gYd2GVg0ePVsQjgUsRk3QqBQxSxWlWCoVuop1SxFkiJotsXKUwiagu40rEhRTlJfw3ESNZ3UiZiXg6pdEQ0e8B0WJ%2F7%2B2uoiY1XhlBC2x0UImbdDqFvmJeyLkEUktElcPY0sw9zhMpgHBlPL7UD7H%2FQAweCVlO06xag62ORwD4nwlQmmuNXw2yfG2RLUqZrF3HRUndBgPx34WcSCDzMUwcV5fbq9FADb1GQ0RJVJWrYvDC7M3%2B398fHp3svzo%2FfPnT%2Ft7JMaA1kzfio4yv3sZzC4172KFYjKuSljE8Pzc0d46IhY06Px8KPnlikhciFjOiZ16VxjAOhI27%2FLIv5Od5XlSlJrEKKW8GYPD7LXoIS%2FsoATBGY1nlsD%2FYUMCRlQK2tJJxgtiMx2NZlml2IVIAAiiCgOWhNGxVvqkH3YjE2%2FhKYuP4Ok6nhG2YYRKPYY4UiCNJC%2Bgzve0LGBXQegM7KG%2BKtAIUIARDaK5Hg58wWiI5BCDF3k%2FHChSkFO7zJBLHizliQMTlbTbWDcTNZYqEoedSqFTIwlkBv8AhZmkJOCxzAMwCYxxngCUkQUYIYQEWdJFm8VRj3OwVoqk%2BANP0yh5qKMvZPnUY6qcHiYTTcIu4GOeLKZyeFI5QTIQDrKfIkaSJApwV4TlLinzOOwfN5rKobuFgVTmcZNjJqCYACQSgwERuw9Sq8Pm%2ByKscyRnaKGKK5vqZZhWXcXl4k73Xk2yLQ1ps3TByW%2Bh%2BVX5cFUA%2FJ%2FEFdFLC5fh2Nsqn4hsQLR0jNzriv%2F5LvYmsXlsrhtK5Ic7QBVT3RRbPYK%2FyOeFZ0zuxYBeWaAzorbsA91XA1wNis9CgiCwzP2D18FoWSEGVzFi4qGO3B1sE3dJEgzGVlT4m%2BuhRm9M0OduqAeU3upOiB%2BKw%2BL%2FsOr%2BCI3pzifxSDwcvZrK4gOfAt4BqMxK0Qh%2F%2F6nJR4vm7icusU5kxrtPYngKPeAyMLK6UkCRqQqoeI5QCRF1xq8cYFxLaJeJWVpEZxCyO3%2FIojNcuoGHLa2gW73GiO0sOmhd3hknS2GWT6UTiMIMTk%2BSZZJ4FmJBZuYDfYK%2FdtsDV4mtJY5SwuSiI5j4TDS%2FCkdLWHqmTtCm%2B3PXrh0WRFw09iHba%2Bh3JqwRupmax2jM66tP5EpgAH4Hzv8XTBaJ63UiP3SRhrABNVhIElpKGLivyFgmcp6sa9MWIhzfnxjpcpk3n%2FFyWjJRO31r%2FNcKzKUB8MWe769UkbR3dXnBQq0FgzI6azhkXD1PK68c%2FgZXDwUvFf5tFRFOZXVSXvXo4xiEyxXe459um6Wn6%2BPHZlteuii8Oi9caT62NaX3MwrweyMmyxWwki459mE2nRmt%2Fd%2F1ebVuiV9QPtLfQ6CygH2wpAV5ZoITmnQy3QmbHbSbxtJSNNnfWSae%2FhYRmAeCqyyK%2FIZG2jwelO1yALjoHIkUdJL7YFN99cbB0N%2FRHXlk6B28kH4fXuIfOaFvNLeF9rBF1xruoT0tjH%2BtJynqSFkLRP79lB2EJm2Yd4U0psUm5tIm%2Fu7994%2F6gNXw9gCvub%2FxfJclL0KA0eD1LgKA26ogPUOT2j9%2BCOVFdambZYJKsnnX13obFes2ZjF6FD5C00gRUG5EtplObhozADKoRpKWNaap62Zqba5EZOVM1dszMwDp%2FaBxWBm3Rq0b25JKtLtIIQdGhhJWjREY4jUGipb2xeH51CzOlY35bthktiNZC8kOZHCoxvh2wryLAphrFEkLfNDrbOxEYpZS1ARWa%2BPSsodFEjd1p4hDZHWDm822NPPfAAPQoHUCdq%2FhUhbgOriik0br9fv2VfmEuBoc2XkyrjvvUEuehefBH6TpHcjLFc4XYdaZp8ri7xhM0VbrMKkEPQTOyuR3h2bnTtVJ3bCBIN2%2BBQOOI%2B6FVYZSqnl4QvXsI8Kq9GcFjQi4zy2%2Byn%2BVtqbewXWRcYat6Raqf7taE67ej0OoJk2JPf1IYsNfSWWMSe37j0BHYZt%2FgIiKw2qeLRJbYBiwpekbuQ%2Fw7vDdNJLeiHYdrZfu9gMnQQIvF%2FBWvIdtaH1ZlJqMrgux0kAesK7tSILHZVJdb%2FN%2BWA0wyId73IMZtGQCsWClnCPEd%2Fp2ISD1G4vIR05ib6Yp7mL0PSJxPAKSzYbbUoQekYjN%2FWLaLv9umPWxLHAFc741iVYGFXhux%2FDdu4y3znRZAXSOK%2FvOX2y489ZMgLjKDi3d1O8%2Be%2FwtpoCw7kD259ny3t%2F0CXp3CmzOLa%2FyZXxOrUH4xtPcupc0ojLVBANXuMP0Eux1OxI4gbrv9Ivia3olN3Qb%2BG52f06zn52TpC9PY8qNnObGamJzgyO01Kg1Yb%2FZ3X5%2B%2FPzo8OTz5n%2Ff76ILm0A7uMssvDUf3y13PewKajvdE%2F9JbOTP%2Bhz%2FP4yKeiSK%2Bsf7KSusP4Lr5DR%2FHVyxE8KWA%2Fw%2FJkhxusk%2Ff%2BGZgLKOkl0IJHrU40xUthUZP3bZ2gQb6W8w9BVKCpvug08KkfYC7HwBXUwvjVOu8pAvWPF9N8yYfx8p1sLbBb2FnuthCxcngDcy1ZdijeWzzR1DWQq8tkxTFsLe9tURWnXpb1qRmF%2FVLS%2FI3VYWaTC1lk85XqD%2F%2BGA%2BM1gH67tkjBJOq0DTBG8jbRvThGhEcR49tcY94uPfcQWJNbDzEhhwM2IUO%2F8PDVbA3fpwXBR13bnGDjkPyzoOtwCEbBcBQWbq4JnyezliKWQ7bWAyj8ScOmw1rK6XbpDpcvb%2BwF9tivef5iI%2FkfAosjyZUy2ajFj2iuLH4wnBQkValnE4waJIXCYAKPGteyFIW1%2FgO7HCaiN7VLt7QHhEs3mZ44ChsEDT4N8mzMNGU82kK0sqbpC82%2Bg0HWR%2FPj0VEQX%2BFS42Geh4wmkUOaOtmrpmLj5XUyEonJsDE%2Fu4YCd0OQahzjEyt3a2khtTvulEUgUFQ%2BvjVqm58E8Xz%2BfSWBDCwrMLARsC3yGLVWx1thrdLAr9WqWzvxwGRr%2BX%2BZg7hqATFgR8%2FwGjx%2Bxg5BPTsK7nfM9HGOLsV%2Bzpah8EkpEBi4MOw%2FB8qv1MSGZSGG%2Fbc4IH%2F2kCQY7wAXT8YyxuRI8gOp6mYH0YUOpWJjN4ADwBxMsoXRr2HvnjWTLCQwg%2BRrULjlgcV9aWAQh9fLjm0RRSL3AHJoDbkwz6YlH0wvJWWWkQrfpPHcMwVOg%2B8bZ7SS625Wa2cJXCrrpkiwrNCZNkLA7QLI1qTgx4xwBgGoLEEdjmtw%2FiF%2FGWRYrZAzhqPzK7TIs8w5aQkloJbgTyuDsnO47LE8Yb6zPEQQ7GXz2Z59tOxGF%2FK8VVZj6l2ErUpxeWBNgp5kZawAUhyaicZpiMF0jaS0Z%2Brci29yPJCrrjTecccVD%2F9YrPWPNSjjW4dnXe94p0PtVd8UZLm6WGmgwjeamKYNAwHYFsdZkyU6k0ztvU1h7om6sBGI%2Bl4sxml8UjOcjjxkyK%2B4P3EmOMvCwlHjHRGSZEszgsAwXHL6q4E%2BwPfV1oNV3OKWTwnf4FKEqGo6SyuYLNLcQlYvcGkjaKk1A0YGTT6GIV7mU%2Bv8QRTgogQu8XFIh5x9F0J%2BJxDi6wUgCzF0UuKWZVEbMwbhiznh2K0YH2Ah0YWIikCi1LYNMKlDg1l4l%2Ba3%2BDoFMIEpngjp1MvaEdLQEzKsuoW%2FK%2FePKDH95JF%2FYejA1EC4VjYxROiUnTEcGcIpwCQPEYca2an1gtLmyHA%2BWQCGkpRGp3nsqrm5eZgkMRVXEHfK9AOUllNory4GCT5eHBZzaaDYjL%2B%2Fsfnz74tJUG89n301GIowOsvD8BW%2BYz0yeCDxgp%2Fg%2F3T%2BbZjOQ7qlt%2BQIuhKSuppjVEuRrwn3fV%2BPYnjImIAiMBaIdixIbCafjUIdd%2Bwm4q6WGamJoZIkTMThXo4YLJBTlVg%2Fg2yDjulyVCHCq7rFKDY%2BI9bWtQHn9acwGocAnPcTm1%2BZ5iGjP8WPQVeY6A%2F4pm7DS2r3hqpXOQqIrgXZ6h%2FU%2FaL0hQ6331Jk7uOHQtEjCXYs%2FP28NWHN%2Fvn7w5Pzl8ffnj3qlM3Yr4aCHToBBflkEUfQJuqhE0IpWqUrcAw%2BsxvoyfFGeuPxW2a%2FCfgNYQRRblK3DfQotYR38Rp1aRNZ1xHXVKNgjJnUqfY6FZG4rArBzkkJvBRSpug3FGtX4rRLVpHAnmcd7h0PuR76NmlTq%2BgkSc5tcGuX7MewHwBtYD6xWb9e4TAOHZEWr5nfRIo4HYk1R%2FeXPYr7bZDlVDB4Lz2Ha8dwAGoJak3Srh3hI09jcYDdxe3l9WE%2Fc8Vu7JcxOi8vf%2B3kAuUiORpDxhPeuFu8I%2FO1Zb1oNbmTW4HL1RH2WgQEJElhvA%2BeVSnVGz4Zct6qg8v%2FKZIz9Vz6xF0aqDfeVP%2F0vcm21T%2Faoq%2BQxUVtV8iRlBNibPLhAn3tUmQtCiU8rvI0%2BA1Goq38TxaoVQxe6y33liggYBCBJuFTdfEBhj4cFAKEwxPE%2FXGJJdxouatOQP4%2Bhh0hXh6RTqTcpPEYppWFaUAo%2Fb%2B2ehAkynMx3mtmIuFTacl5n9SKiCOBnoEKHSYZHnDSjyquUp1HwpkhTFAQPYhZmbDrIu0ZEdCdZNDjxKzPS1fHuis02krDvjc8kMgDFBxSoxlegjtIw299QwinXXEfZgu6tQje9xm%2BlHtaj9AOWA3Pk2tRBGKG2XYJBWPbW8VYOo18ut8UTQ3RTdiaLB%2FEB7rcDsAQIczDu%2FVXglX2kCLx49D8gXFFsG7vR3EgCe1GubNLJ4iUQLbZRJnCqUwEhs9cWO1naCgA%2FzsY1qsOimVnJFXIRadOWizMfRPkw6pVJzKGU9FnCSp%2BhUIPxIHbE7U7ZlcgSclt%2FY85CjLKqTXqwyWgwmG2NEdj4wVInbVPuxRIFPUdbF94xEjZtLWdrePUtsbw11uKROpscOu55McR%2FbZILdu1xvHc9Jah2In8l0B%2Bgcd3VsCjwTMCr88fhwILj%2FkLLhta3TUuRkHSd9f%2BT1JQoRjimEmdL5wP%2FF3TJjOgb%2BSK4dZ1xR5lCa%2BOLmOyQxlBozXJpBAlF8VR1DGaEyXPYwjDYcH9nYLjBJGHskp0AtSVRLPkbop5HwjRygWVywD6yKtLhcjUMBmA%2FXW%2FDua5qPBs5H8Yf3Z0ziRG%2FLJ0yfjjeR5Mh7FP8ST9ckP38vvn8STjVEy3hhM05G%2BoTCwJPSRfR8m%2BlR%2B%2B2bje52g7YnpbZWD3e2YN2jbwCs8iF6ffRPFa3ZSXoJQL%2BQF4T74BntYHhOSrgRcl%2BCwvaz0ANkc%2FRLh3aBFSazNMd2ct9s2m%2BU3QMLITLrdSQZqwySL6PFeDlhbW%2Bt9VWvQ%2BJwnjx%2Bj%2Fyfr9kLe1psinr%2BS87KbwH889QkfRaDud%2FGla1mQW35uYugWm8fHtuIXykVtqG44fs%2BathmoqZVTbtuW5cLbYYKhMViuF1n39KwtTZB3ZFOsN976yX%2F1HJgOs90y3qlPmGduina4LRM%2BNNUbquisCVQTJsAH6cqkdzq7ZP9glLkBmq12%2Bj8Bqm82vOuDLC6KB86KJwvnhB7%2FmzkDzxTlkHLvtA3w4oZejT%2BhbQPE9lsa1fuFS7dmqVX4O8%2FlrRIXRnlyS86iXTQ%2FW%2BIbdsqCS9a6I5zxZRSuqXptQ8Fj3460x4U1GqaLOtIxCLqe3eCLMS6UMdHXdsgmhgG0DXdnbmEYUypsKLlQ1yPY0Ic2ww1m9ANtvTPk7q%2Fh0uZouYRi8GBY68SX62oNp50xOng7Z13e%2B2YEz1l5XIEZDqYJYbiGiZIuWxwsaiJr3Hq5GPjtXgein3ugEqK8t%2B52gWYfJ%2BpaRlpGTg%2FKVST2PXfN%2FNCKQ3zj%2Bp6oNr8OX3LS4a6Ols99C029B%2FX0IlehEczxuwQVfCpJ4rzim5vZGM0yW%2BLVG6aSDFAmwjJd8bjltYVdPJIlhszZjWf1VXIzyBlJevp8sacslcaLVm6XNDfG25QGwF%2Fq%2B4Xa89B6cutek6xxcHG1aoSuwULPF7K1DmILWBsss0mTTHH9kL7wC1GqOcPf1KcV7ZRfgupA3QaMJGjTRCOPjJqb0cu2A6kFBlRXpwpLsF847N9gHrTue0VTk35I74L%2FNthcVyHMTmrRsXwbUBAUmvlu1vTaNaqgswkkqFQLFOu2n34i%2FEc8JV1Ua3IKS9bflzGh6aiV3QSt71ZdgZugnO22nPy%2BvVA39hJQ5bcbYRhPl1%2Bv1eqGXzjWXui3KulRX54T81IuklysTuIruSo%2BHL2p7zKbswm%2Fol%2B4kNO4Sq%2FZf6wvpH9E9%2BiHYnrE14lfysv4OgWbBkw9yg7KTbe%2BQLe%2BuZ83RDkP83V7Q05iG%2Btr4GJRTE2AexTDRi1K7XLDKXUY2NALjHghM3SXmZDoWnyR5WWVjnGw0ly1T9IJ3WJHLypsA3qmdY%2B%2BSCMpyrIQA8EVDugm9HWeJhSXvE1UahAQB8VWIzvaCv9DSDFiqq3aTgmGH%2FvtBEX2MRZJQ2zSgA80eJ%2F%2F6dmz9R%2BfbDxff%2F702TM5%2BX70%2FE8%2FPps8TybPwND904%2BT8fqTZxvrzx2D90jhHDfGM3itpE29M7jr23Zo3jzuptl8UcEoroaIeWHwUClrdjuQiZ83Bx1H96CsJ9I7lDhGP0mdbJdmerwet6Q0VLIJ6KnKSsWO%2FD66LOSEkkR4Tucd0mbG9xz1%2B6jglKzu4HTn27Po0QCA1BCqXnyBXWccl3yXe5zjCjsdp6W%2Bs1m3rfKfjg%2FfoeiNouicUpG2X7iwNRbMXXth7YJzmiiBsD7s7XcUYeBJerEIvlN3IC281obB1oq10fXtdViI83cgweIDbY7pa7jJhyqdptWtczCtq8jXcZHGGI5Hx35GKyJXIbPHJPJTU1X7LuU99MnBDnrVW1mW8YVRFBuXKQ90P7xH6fbhkXp0n%2FKuZoFltRg5MM%2BwcIOVomDqN6BvP8uzNd0Y%2FZ10i86DXXU9hoG75352UcMTrBL2gcsBjMLKo1FZmCVXcZBJJ5xR9C8ViFczUkYR1Z4Y1hVXhm4VCusaYIoX6m%2FiW04IGnOAdER3w5P8hqOCsZjmwLx5B0dYd6MBBB6Iejo70SrsblXuRSt%2F4y%2BpSmL2AjCxyNIxZ3CSJJoBaUJLkHvjK4yhjHXNi%2FBpUsMoZT10ebujJpT4NzHo%2Bs713R9Y64X8fI9GQA2lLB49sOoLoPPBRV8EcLVLAGNScWoMZe8wPLrFAo5s%2BQcUh4kGKA4HTBFWcZi21vw%2FBs4UlmHgTE%2FxoaRSD%2BKjHH3Miyt92V%2BqKIReEycpUn4UhURIhcCZlPdVYXzvQTU%2FYJniOF8UY3nCbQaPvj0%2Ff%2F%2FhaP%2F83Dry3bqNIWkkHEGkY2j6Ji7tghNIF%2BMYw35cpkKoBHZaJbJIpkgdI%2BqUPGCdAIN%2F8cwUV6d4pAnU8%2FuBBf6p9euqUgxWUdSu43%2FMk62vhz%2FGBA%2FUmTRX0ZnfadUCpg6n3AMlJ90RkBsEpHrwG2AM4VgjVlzmGnYecDFPoHMY9oxjHXjc9CpKDIgY19Y9a%2FpAY9OantCa1AMn4F53AC5kkRdejSB3TzP8lRr%2FmSqw1ODSb01%2BiOmhBzLyQQWkGiM123BJM7dhbUkrZp9Xu6aXEsN1CKs0y9K%2F23klFHY2OwmDHsm41BUMSrAQxpfdegS75AWe%2BPVN14BvDgSQDylSqjkH13rRQWLQH2qY7oauJT0C7fRqy51x40EzeuSoJLeKiCka%2FtqZnzxk5o6emfWvv749UlTeWTqBujrgz6C1M3sL7d3YfjH8kGGUOFM7S3Jy0ywNG5nKFk6G4PCtRoImlLvmof7uS2CRd32TfuEpEUqVMgQcDR3XOGZxEzW3JjeZFgeYmg6aX3dDpwFHmBFc98OBW0RMhAaFGWnLnf8gS2ExUwsMZOL2yPdBtK4a%2B%2F0QIs5Bay7YdA4fxcD01p2OcKpX4F6HmY4SyO6fyqYKZj2aa79JKfG0zh8z7Bz4or6PZrNGHbArySKsB2HPln7SCCuGMhFMYxMjRGur4fjyOSnd2jd93eyqeioDp05ZeSHW0Qnkv6WgereLDrm5fxWKnDFoatUyrpIznZBB6Rx8YYHi9%2Fgb7JdJPyqv0rl%2BiNk2pZxey9KMz4mKOi2OMjRd0BouwPZdtOVHY0dntnBp2VV%2BG9haf%2BQl24xJY4evDrvxVH6%2BSovyXz3xivJUOEMFFX7KUdmxewRo41SPfvZVdMEwhokjAksD7wyqbd4y4tAJytSwuOiwKMgjkON8Zlgj1w1dThtR4EyE50IG0LoH4ZSoIMF%2BBXAPJdxlxOsuxvOW21RcU3KYFE9yymhshC%2Fxx7pdanVBMdyGMS9viHKjwuRTZ0jRg2AMogknBSPsbvfHq8OLUMvGpNnGJN4i%2FBDsw2RCYy4P1DBW6kQpq6cJGXtDBMma4ifN9jU%2B6oU8kKoaQYevRYWbM20BRf6e4mrpQSrNAeG7ubfmBv0DDr%2B19wGK%2Ff0IOTBKkKDbNz0wQtu2h29AB5Zqr89bU2g9DV2hwfUO4AiRZ2Yk0TFU8S1k9GSJfJqQJwm5iAK7ZKU2rcBKLWIqT6vy9KxGxj%2BE%2BcXk7UEr1dzUAU2ZrHEZF9PUvtisIaJwf7JQrlecCvSMjFOkcdK%2BsaJrvwqmk87Sf3FUpCLrE1OVZbLAu8wYjFEKAt55vdG5gS176G5faM%2FsXWJ2boShLhTJJMxEWZ9LHdirSyFpezaliBPGZWTyEi91ZckbfRS1XWvXKx6ggoBnhjzEpCGQXh0JsD%2FGFFChxHX0AHOcKcWiuL8sYvKLq0RJFiuwGxrAgB3y8vZDMWUrwIq%2B%2BNo0tVpmkGDfZfbIG5v50Gj%2F%2FlU%2BzAJpxKAw14y8lNvi5e7ez%2FvvXkVmXCqxmjgDWujAMTjbHK397eVUwHW%2F1FyW0q46uxW2%2FCSO%2BlrF8jmA9Pne8NJmfbPmvk3p9sUltSLdjhPyFBS9iDKGul06x42MEMQIjmr7WPTPMl%2BLWXHA52LGNuM2XC6JDog%2F0O%2BifzwnhQPFxkOgeKi75SETPnnAhB1dZKvV73LPTEE%2FjP75nf0x%2BueuQSJSZSxbEbfXwMg5IIELNnuoT9wd%2FF5j4g5ekBzZEUOK0OEfd0OxKTqduyHmCPDLEIEtvKqrd3Y6oQc5wRmpSHCHDgqeJALZw7u6yYdvLGlj31C87%2FB264NJRzDk1aIX6vLTv4u%2F3q9OYguXry4orq8v%2FFmJBLVPqlkB4Su4%2BUKJJO9eIqorI%2BBTC1AbEASq5y3wirlfu1mxMwQEb%2BWrhNZwDQddRu2%2BKg663U6kqyXt7JiHywToEecuNwEyQfEsX8vnpFaqMazKUAwMdgwucVchhLaxbutpA0P64MVAe0uxBUKPx2kZ5O9ryO15GhdGY4FpKJQZpIvp3FDwLbIWoqyMKbpyNBsvNUdoXCXl4N1LGBZTR7ixFQg%2BqKjkO0WQ4kzlENFNufqeCd0oQufBKM8rOJ3xfE51f9ghkGYTLLtDAW2%2BFaWKlegp6sDa6FbMc%2BpLiUJ48Z8OGB5KutAiwJrHULqs9AZzkHZo9AgDAooVLC5Uf97k%2FOPh0c%2F7R%2BdvDvd2Tw4oS%2BS7L5guErGvNJ3cdqeq1o9KQundba14g3gfJ2mMYL8PdH%2B3%2F%2FcTNQbg%2Bzg0Au9BpNDc7ZHXLMADen0unSae4Dy8RYyOErNflk9Mg47x8zD3IOmxGPdqWHpbw1pnI1pk6YP0o77Ugz9mF%2BiJk4bOgq6D9D%2F4BHYHh7TdwurqMGHqC6ehcjYBEijOuVSLHjHDdMjanCOrlIit96hEcj%2FnxbR10rasiFmDayvAG58xsPrYcYEQ7%2BWqGW%2FqBD%2BVW6Cyom64Joc6Sqpo0ERieRGOWrVcFg%2FLDo95fffF%2B9DPndIcKIKNVbGqbmfQYYokdyjoinkiPxwd4E3XPMOSLPNeL%2FqUpxm1vNND8oG4cyM9jXPMoPHvbSEOlZZxT5DDatr0fGttSJhPf7QfUP9rIDvtbSNgXt2evlDPk6PJsqvT0Ludshi7%2BXjwAKBIZAONGkY%2FYe47zphzr1KgmNnGsSJyLpQfUxBS3l72AHRqQbXNvJfGK7yJbZxTqGsCaCvqQn7%2BqWTkDf4RfSq7O5v%2F2Dn957dnj3o78Pu3Efz73aD%2BoBAXOUrx%2FvhFin4MHHCAJA6qGxdPEjBM39yInd6CcMMKdCwRdrgUD4i7b3URGf%2Bklj%2BVBl%2BHRYCya6ijCmteeI295e2V9frG5e%2BzQBjnf7VCgKnNA2HB7K6u1wirfpSjXdDiZqPprR3VlMmFYlR9JerLw0bhBNuwt8cJeDqWjhpMm7tRvg9r4K1W0BVPDU71MKDVCA8APQzuogmu0TSXf58L85%2BW518NksVsdut%2BwEt5sukbOJy62wBpLJwP%2Bhjy%2FIusKB8mvV%2F0uXXEUDNzUtD4E3Tw5AHJaO7XiewSXq4stXAeNhrM%2FTdrbae6qfXJopmz%2B%2B7TiMzJcBEAu0X4SoHzCaCGJblM1Nd5QpFadbvsL1JQsUqr4oX%2BqNmYP%2BHk7iDmq8D60krnUlCrxGwjJeeNbrkMJxvJK7%2Fn7pqrTkurs3H5IW1xqvOkXV1Ltjf9z9zY1N1SXqO7uoiKBd1trYS0SGuY5alWgVoKzVQxjlUnlhdUF8xx%2Bn3TWuVTf9ELdchLymTFUXSUIM3qEoScE06%2BMiCWeV7KcsBOM%2BvSJRJUdBGxIUgxrSsp51hitpTVCdB%2BvsBiYkUOupT66h3XSZSf5ZjuQmK4BdUge0gMv5gcXxo%2FNsng3dUyn0kqabDaG9KFljqq4Sd2L8mAW7IhgdwXQ7HLPjBmOzza6uN7FC8an0J8d3iyb%2BdDmN2awAIMnjVAqIkvMipVaOXQkePN1nxVkUK22tq%2B0cggoPu6JheHrLrmnk64650g9zZdD3MPqH0s%2BSqYfTwb3r87jw80ypOapBxTuh0pPtzYo36wpshhzKWN0mK8mMaF5QMHPf5TuSHWXmDN0if4L%2F5tOSJNWVQXgn7b9AEuo7f87vcSt7pcKGeu8V98V8rlLkYOsbnsmWF2v9P1MytOoyjrPXqaSkOqH4PeH4yPqsKUWFA1u6gLqnJ%2Ffb2NK9Igadu1leYLsIFv66tcbKIYgrBhtBNfnjjWoDPdtnAWtnHWkgzg9wp8deXeAk%2F2TH3M5%2Bd6TdsooTcalZ5CtKF1V3dLLY3JAfOe%2BxGN6wlYlTOdpGPtX6hvQVh3H14dvrUrPN5z%2FYFy%2B%2B1J%2FpC7DPw%2F5f4xl%2BzohsPDleyWSw7e13MbXpTgJ4hrZ2mLl1Bdv0zpNqJy2Jb2TneX%2BRh36q9b77ift95xnAs7kXIv7NQug392o0fdne1%2F7PR%2B%2FWf06Lue8h1gIl%2BHKufhkVZ0tlV%2FnGxeKv8SYstcEiWFAMQ%2FV3VX7uoisu4wjtnTxC%2B8XPRuXdNSTegUP%2BCUWIfUhU3rcybyYNUpy53zkFCJ21mvQ6gS4vxtT70I25a2%2B5rV63yGwHcE5op9NL9jUo%2Fi5rTVLED%2F2B9cMh8upyRfkFo8QWR90TwUCvY61zy%2Fjkq5Q7fXuDHN2pHtThQYCutS0O5y1g0VW9cZMSaXkAXCTWzd%2B8WklosLviWsPy6L7aPGDKFtdEBfGlfVajEmtVCpQiuAAjyPY%2F2cBURl1WZxcVU2cnxLK7vdzbRp5D42d5Hdq96mbL9YlpfuNQ591kLN43%2BDviU%2FNUCA2rC1SM8frOX7XV%2FvA2jSTWulBMsE4QtIeEkIQ8LqS7Tkkhtz8hnXMtaxNJ2uRTlc6iBjqHdsJVbpAbGK3wgvDTIBqE0FzufluYhwoku4qkuSm9D1svwYb5nMKj33k%2Bie2yOc21Hem7ic7dVIPl%2Fu7tM%2Fmj3%2BgtfRMcBgO%2F2cIYN89YsyfcdcToTp3hoisizj4wpO6wwrVsN0nrMwgDY9sGtPPQRL6jLLb8LV74Yfp9awjRG8IA1Km4ONZs4dP3D9a21CywLZKl9b6Ax%2FI6rJmRCgOvXRSm7lI6BRENd9URfGdTHWUiA3zTJZHOm6UuovMptC5XLsZK66X5NrmAq71oAe92%2BR7MFqbuploj473CzhpiTYMQu01maNsr3eBJteBfAQgFr1oHyKIvQVSau1r5%2FQykPTN2oEm9beXrr0U1r0Y%2BoIFQ3i5TlU1ILb2IaPuUH6u7LvMPN2Pqt4Hx9uSyb8Cq2RTVa1dS6ZtH1YR7duFv9yRq0hJvu36XUO3fXwC8DW2WKlMNaS%2BhilbdJhnRxy73Xq2yD%2B4LoybcoOKjAio%2BAR89AQpGOu8%2BhEv0JqCmqVx8d6AUmuvpjF1gRCMeN7KExDsIRyMb4Us0VJed%2Bow6GTogyNq1Lxlbia3jYVzvuMgYaC%2BVHWn%2FKJ1Sc5fjq2FM0A5BRHxE9mODbS0B96JCeYJq4v4yBm7RuoaLg5kR%2FAyKXURyYelfR7PvGHHTbXOOT9xWyeAqTxpb%2FHX0XDynftJLHc8%2BFzwiNSIRfNMJb115IPegI5JuLsGfuEuP9P91DfPak2dH2lxZAkIJ3UnaWpOC0WzIO%2Fbg9E0alUSpb%2BhiSb%2BnTSMWhtJ4uiy4KQ%2BpVfvde3%2BXAZa082fljvoUyhz%2BwQxRCTxhsy6KQiNyk5Cy8WYFZklToacDBlOY7n0rPxdJVKZEeJZY6aJIo2XD%2BQl2g1RV6n%2BaJ8k%2FL1A%2B2DiShYfyzx28V5sQsG3HAKTU4LOd0uq1s4UZdSVmenWBdpe9VC5upZv7XhP52WO8uaYktv7fcP7XeAGfwd1Qhy1n2Pcai2%2Bg%2FhvGrs%2B7kv%2FtzHgVsJ1d1zRKK91Rzi2edqYd0Ovu4ERsYffAezU5GqegtaksqpsSqcpXd9Scs80%2BGSdq3QwwKFo1pADdQLtqaa8s3J5TP9kZuuxn%2FYxnvLbt38JevGT76RI9sUw7sEpWZIQlkVf6NyVyA9R1RSKwyJIRrsHbFrfO8ynSZdROz9Do2vkTcuhzLichmPYm%2F7aVmMfaZUv2lyIbdXgO14nX8Dn1HQP4zTnFD2Y1qyFEHbXCVE4r4xLOYK5YRvQhifInrsbmTbyCwYE1lRuUWwKCIqY%2FPevtHH33zTpqfWfjCGGCYJy3emYANpu0uJzChtfRT437C1f7g%2F3hTeB3uowpuPWGSx2%2BHS9P17ziv%2BPJA74E%2BonDY9%2Fy1MVS29na2qDOCWOdXKOU9yObNkjRA2ir6Uh1zGuiCpLt1SKHHsEIyxDlUmQhKuzI4f26W0BU6WoC8Hecp4JP4a0KWN8sw6c9vgraq0h4l%2FjzT4w7kir%2BahfPF3V22XKLSWp%2BJhdupSW8crp3uPpzDwFV7sEEr%2F93rWH3Lo1TWiWECf5EdaNNt1AWuLZWsl9BQ9YAJtl00vLofph97ApkS60xJj0gTN%2FwfWvrMA%2F5cAAA%3D%3D&config=H4sIAAAAAAAAA31Vy27jMAy89ysCn%2FewKBY97LlYYA%2F7DYJiUQ67smSIVBqjyL%2BX8iNJGzq3mMMhKT4mH0%2B7XfNGbfN79yE%2F5WOwmSBfvsVCY2R7EkvD4wDUZhy4%2BbGiTBXyNhBMpvOMNGxzB1xZQM8%2Fn38tjCakRLAyFluPEf14m7NN%2FZCB6MYmVglZeohMX%2FkLltN7BTiXW%2Fs%2BpQA2PkCMJYORoYOsBW5TCHYgMEeblSi1UpuRkpaigoXBmSGnQcWjQ8YUJec96sA60yYHCoQZWsYjaDTJJbRI8jzlPRPsYF%2B6bprzNzYcbSiWlZxwmkYi1SpRDwmJjS9Ra%2BEMbvRgBpfmfmeiNxm45HjPe0sYN2byH0A6ECxRtD1ocScPL%2Fu0xfYPmRi9rCyPCi77rb0yQidNNYhe6WztDGRGbZoZXGmhdrbVylngjfYROjDgveyKEprekduDlrQeevIKIPO1XtuqGTCXK9zA60E8gP%2FIK1lfsMWjt3zYRmns9yk8SNADH5J74CCj4LQNZ1GJ07CNl%2BhAVgOc6lJoAu5FQA6AkwmTXt7thpyHRDRdSPurTCwO54sO9zZ213v%2FIsVSMWSswmnDrchCj%2FxXVEIW071eRXXmPi38pk%2BuTIGXP4i6G7OsvzRXp1XB1%2BobpH8rcar3%2FAknD5V8awYAAA%3D%3D)
…pp Router (vercel#87389)

Flagged behind `experimental.strictRouteTypes`.

Most notably this disallows `void`. We generally treat `void` as "forgot to add return" in React e.g. 
```tsx
async function Page() {
  <div />;
}
```
which is a common beginner mistake. The downside is that this breaks unconditional `notFound()` or `redirect()` in Next.js. Those function throw but even with `never` as a return type, [TypeScript will not infer that this causes the caller to return `never` as well](microsoft/TypeScript#26537).

```tsx
// implicit `void` return type instead of `never` due to calling `notFound(): never`
function Page() {
  notFound()
}
```

The fix is to explicitly annotate unconditional `notFound` usage:
```tsx
function Page(): never {
  notFound()
}
```

Conditional usage would already have another `return` statement. If that's missing still, we'd consider this a mistake. You can always do `return` without a value to fix the type-issue.

Pages in Pages Router are not affected. Tightening types for Pages Router is out-of-scope for this project.

Closes https://linear.app/vercel/issue/NXT-127/
…oute modules (vercel#87398)

Reverts vercel#83239 flagged behind `experimental.strictRouteTypes`.

Makes the error messages a bit friendlier since we no longer need these `__*` helper types which made it harder to grok what we were actually doing.

`satisfies` is available since TypeScript 4.9. Our lowest supported version is 5.1. We could land this unflagged but this just makes it clearer that all the type changes are behind a single flag instead of being spread across flagged and unflagged.

Closes https://linear.app/vercel/issue/NXT-128
## Summary

Development scripts for profiling and benchmarking Next.js dev server boot time.

### Benchmarking Scripts
- `benchmark-boot-time.sh` - Wall-clock benchmarking with two metrics:
  - **Listen time**: When TCP port accepts connections
  - **Ready time**: When first HTTP request succeeds
- `benchmark-next-dev-boot.js` - Multi-iteration benchmarking with statistics (median, p95, stddev)

### Profiling Scripts
- `profile-next-dev-boot.js` - CPU profiling infrastructure using V8 inspector
- `analyze-profile.js` - Analyze CPU profiles to identify hot modules by CPU time

### Analysis Scripts
- `analyze-dev-server-bundle.js` - Bundle analyzer for dev server (generates treemap report)
- `trace-cli-startup.js` - Module loading trace to identify slow imports

## Usage

```bash
# Benchmark dev server boot time (5 runs by default)
./scripts/benchmark-boot-time.sh

# Multi-iteration benchmark with stats
node scripts/benchmark-next-dev-boot.js --iterations 10

# Generate CPU profile
node scripts/profile-next-dev-boot.js

# Analyze profile output
node scripts/analyze-profile.js .next/cpu-profiles/*.cpuprofile

# Analyze dev server bundle
node scripts/analyze-dev-server-bundle.js --open
```

## Test Plan
- [x] Run `./scripts/benchmark-boot-time.sh` locally
- [x] Verify scripts execute without errors
)

## Summary

Comprehensive improvements to the PR stats action for more reliable benchmarks and reduced CI noise.

### Vercel KV Integration
- Add `@vercel/kv` for historical data persistence
- Track metrics over time with `loadHistory()` / `saveToHistory()`
- Display trend sparklines in comments when history is available

### Comment Generation Refactor
- New `METRIC_LABELS` and `METRIC_GROUPS` configuration system
- Organized metrics by category (Dev Server, Production Builds, Production Runtime)
- Better formatting utilities (`prettifyTime`, `formatChange`, `generateTrendBar`)
- Bundle group totals for KV persistence

### Noise Reduction
- Significance thresholds: `50ms AND 10%` for time, `1KB AND 1%` for size
- Additional `<2%` filter for long-running operations (builds)
- Filters typical CI variance while catching real regressions

### Stats Config Updates
- Add `measureDevBoot: true` to enable dev boot benchmarks
- Fix `appDevCommand` to include `dev` subcommand
- Add `--webpack` flag to `appBuildCommand`
- Rename "Client Bundles (main, webpack)" to "Client Bundles (main)"
- Add `turbopack: {}` to test configs

### GitHub Actions Updates
- New `action.yml` with bundler input parameter
- Workflow improvements in `pull_request_stats.yml`

### New Files
- `scripts/test-stats-benchmark.sh` - Local testing script
- `.github/actions/next-stats-action/src/util/stats.js` - Shared stats utilities
- `.github/actions/next-stats-action/test-local.js` - Local comment testing

## Test Plan
```bash
cd .github/actions/next-stats-action
node test-local.js              # Basic test
node test-local.js --with-history  # Test with trend sparklines
```
…sizeLimit` when validating route (vercel#87633)

Not flagged behind `experimental.strictRouteTypes`. This is just a bug fix.

Got revealed once we typechecked routes in pure Pages Router apps e.g.
```
.next/types/validator.ts:76:11
Type error: Type 'typeof import("~/pages/api/hello")' does not satisfy the expected type 'ApiRouteConfig'.
  The types of 'config.api.bodyParser' are incompatible between these types.
    Type 'false | { sizeLimit?: SizeLimit; }' is not assignable to type 'boolean | { sizeLimit?: string; }'.
      Type '{ sizeLimit?: SizeLimit; }' is not assignable to type 'boolean | { sizeLimit?: string; }'.
        Type '{ sizeLimit?: SizeLimit; }' is not assignable to type '{ sizeLimit?: string; }'.
          Types of property 'sizeLimit' are incompatible.
            Type 'SizeLimit' is not assignable to type 'string'.
              Type 'number' is not assignable to type 'string'.
```
-- https://github.com/vercel/next.js/actions/runs/20427462435/job/58690778302?pr=87628#step:32:562

Closes https://linear.app/vercel/issue/NXT-121
Reverting since it produced merge conflicts with in-progress
[strict-route-types
project](https://linear.app/vercel/project/nextjs-strict-route-types-2f0a70110d5d/overview):

The lesson learned from the earlier PR was that this is a risky change.
We'll land a similar change flagged in
vercel#87768
…d even if .next is excluded (vercel#87768)

Flagged behind `experimental.strictRouteTypes`

This fixes issues where cache profiles where not included or routes not validated if `.next` was excluded to squeeze out every bit of TypeScript performance.

It also fixes a redundant type-check since we have separate dev and prod dist folders.  If you run `next dev` and (`next build` or `next typegen`), you'd type-check routes and links twice. Now `next-env.d.ts` only exists once where we decide which dist folder to type-check.

Going forward, new Next.js type-checking should be added to `next-env.d.ts`. That file is fully controlled by Next.js and churning it, does not churn users since it's not in version control.

`next-env.d.ts` will be moved into `.next` in a follow-up. Ideally independent of the dist folder i.e.  independent of `next dev` vs `next build`.

Closes https://linear.app/vercel/issue/NXT-124/

vercel#87319 but flagged.
This auto-generated PR updates the production integration test manifest used when testing Rspack.
This auto-generated PR updates the development integration test manifest used when testing Rspack.
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
)

`cargo test -p next-custom-transforms` should work again now
…8116)

## What?

Adds [Conductor](https://www.conductor.build/) configuration to enable
team members to use parallel Claude Code agents for Next.js development.

**Files added:**
- `.conductor/conductor.json` - Main configuration with setup/run
scripts
- `.conductor/README.md` - Documentation for using Conductor with
Next.js
- `.gitignore` - Added entry to ignore Conductor worktree directories

## Why?

Conductor is a Mac app that orchestrates multiple Claude Code agents in
parallel, each with its own isolated git worktree. This enables:

- **Parallel development** - Work on multiple features simultaneously
without branch conflicts
- **Isolated environments** - Each agent has its own clean working
directory
- **Faster iteration** - Multiple AI assistants can tackle different
aspects of a task concurrently

Sharing this configuration allows other team members to leverage the
same workflow for Next.js development.

## How?

The configuration includes:

1. **Setup script** that runs when creating a new workspace:
   - Enables corepack for pnpm
   - Validates Node.js version (18+)
   - Installs dependencies with `--prefer-offline`
   - Runs `pnpm build`

2. **Run script** that starts watch mode (`pnpm --filter=next dev`) for
fast iteration

3. **Environment variables** to disable telemetry during development

4. **Gitignore entry** (`.conductor/*/`) to prevent accidentally
committing worktree contents
wyattjoh and others added 27 commits January 6, 2026 22:19
### What?

Adds a configurable `experimental.maxPostponedStateSize` limit for PPR
postponed state body parsing to prevent OOM/DoS attacks.

### Why?

The postponed state body was read entirely without size limits, creating
a potential denial-of-service vector through unbounded memory
allocation.

### How?

Enforces a 10 MB default limit (configurable via next.config.js) with
byte counting during body parsing. Returns HTTP 413 when exceeded with a
helpful error message directing users to increase the limit if needed.

<!-- Closes NEXT- -->
<!-- Fixes # -->
Update to swc_core v50.2.3 to address a parse issue with mdx files that should be fixed by swc-project/swc#11372:

- Fixes vercel#87713
- Internal discussion: https://vercel.slack.com/archives/C04KC8A53T7/p1766716756273609?thread_ts=1766712717.419489&cid=C04KC8A53T7

I'm intentionally not updating to the latest SWC here to reduce risk, as I'd like to cherry-pick this into the Next 16.1 branch.

Changelog: https://github.com/swc-project/swc/blob/f9b4da2bd85d160b3ee4b3296ed520388675b90e/CHANGELOG-CORE.md#swc_corev5023---2025-12-15
## What?

Improves the error shown when `generateMetadata` or `metadata` is
exported from a Client Component.

Also updated the documentation to further explain why it can only be
used in a server component and the steps to follow to resolve the error.
…88157)

## Summary

- Add push trigger for canary branch to `pull_request_stats.yml`
- Remove redundant `releaseStats` job from `build_and_deploy.yml`
- Rename workflow/jobs from "PR Stats" to "Stats"

## Background

The stats system was designed to save historical metrics to KV for trend
tracking, but it wasn't working:

1. `releaseStats` job only ran on actual stable releases (rare)
2. When it did run, KV secrets were missing
3. PR stats had KV secrets but didn't save (because `isRelease=false`)

This change consolidates stats into one workflow that runs on both PRs
and canary pushes.

## Behavior

**For PRs:**
- Compare PR branch vs canary HEAD
- Post comment to PR
- Don't save to KV

**For canary pushes:**
- Compare current canary vs last stable release tag
- Post comment to the commit
- Save stats to KV for historical trend tracking

## Test plan

- [ ] Verify workflow triggers on PR (existing behavior)
- [ ] Verify workflow triggers on canary push (new behavior)
- [ ] Verify stats are saved to KV on canary push
- [ ] Verify trend sparklines appear in PR comments (once history builds
up)
## Summary

Add per-metric significance thresholds that account for variance.

**Time metrics** (high variance from CI):
- Dev boot: <100ms AND <15%, OR <3%
- Build times: <500ms AND <5%, OR <2%

**Size metrics** (deterministic):
- node_modules: <10KB AND <1%, OR <0.01%
- Bundle sizes: <2KB AND <1%, OR <0.1%

## Problem

Current thresholds flag insignificant changes as regressions:
- 3.45 KB change on 457 MB node_modules (0.0008%) was flagged as a
regression

## Solution

Use per-metric thresholds with OR logic for very small percentage
changes:
- Time metrics need more generous thresholds due to CI variance
- Size metrics can be tighter since they're deterministic

## Test plan

- Verify that 3.45 KB on 457 MB (0%) is now marked as insignificant
- Verify that real regressions (>0.1% for sizes, >3% for times) are
still flagged

---

Stack:
- vercel#88157
- **→ This PR**
…cel#87946)

## What

Adds a `--experimental-cpu-prof` flag to `next dev`, `next build`, and
`next start` commands to capture V8 CPU profiles for debugging
performance bottlenecks.

## Why

When investigating slow builds, slow dev server startups, or production
server performance issues, having access to CPU profiles is invaluable.
This provides a first-party way to capture these profiles without
needing to manually set up the V8 inspector.

## How

- Adds `--experimental-cpu-prof` flag to CLI commands
- Uses V8's built-in CPU profiler via Node.js inspector module
- Profiles are saved to `.next/cpu-profiles/` with descriptive filenames
- Profiles are saved on process exit (Ctrl+C, SIGTERM, or normal exit)

### Profile files generated

**`next dev`:**
- `dev-main-*` - Parent process (dev server orchestration)
- `dev-server-*` - Child server process (request handling and rendering)

**`next build` (Turbopack):**
- `build-main-*` - Main build orchestration process
- `build-turbopack-*` - Turbopack compilation worker

**`next build` (Webpack):**
- `build-main-*` - Main build orchestration process
- `build-webpack-client-*` - Client bundle compilation worker
- `build-webpack-server-*` - Server bundle compilation worker
- `build-webpack-edge-server-*` - Edge runtime compilation worker

**`next start`:**
- `start-main-*` - Production server process

## Changes addressing PR review comments

- Removed signal handlers from `cpu-profile.ts` to prevent conflicts
with CLI cleanup logic (telemetry, traces, etc.)
- Added synchronous exit handler for non-signal process exits (errors,
`process.exit()` calls)
- CLI commands now explicitly call `saveCpuProfile()` as part of their
cleanup before exiting
- Replaced raw ANSI escape codes with `picocolors` library
- Added comprehensive documentation about profile file naming for each
command
- Added build profiling test that verifies correct profile generation
for both Turbopack and Webpack modes

---------

Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
…ercel#88182)

## What?

Adds `experimental.devCacheControlNoCache` to test `no-cache` vs
`no-store` for development.

Note: This is for testing only right now. If it's an improvement we'll
change the default.
…vercel#87106)

### What?

Making a batch read from database can be more efficient:
* Order keys by hash for better cache locallity (in AMQF, key blocks, value blocks)
* Use binary search to filter keys by min/max hash of the SST files
* Only need to check family once instead of per key

Prefetch tasks with batch reads.
Add helper for "for each task" which can use batch read.

add tracing for database reads
…74818)

## What?

In order for Next.js to know where the root of the project (i.e. monorepo) is we have a heuristic for searching for the root by looking upwards from the application's directory trying to find the package manager lockfiles. This works really well and in practice you rarely have to provide the root directory. In some cases, e.g. when you're creating a monorepo based on an existing repository you might forget to delete the previous repository lockfile. E.g. in vercel#74731 that was the cause for the issue. While having that lockfile in the repo doesn't do anything it does affect the project root heuristic because that unused lockfile is matched on the filesystem and is higher up than the actual root (in the application directory).

While looking at the reproduction in vercel#74731 I realized we can consider `pnpm-workspace.yaml` first before matching the lockfiles. Still need to verify if we need a separate findup call for that or if it will recursively look up per item first.

Fixes vercel#74731


<!-- 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

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### 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 #

-->
### What?

When expanding the followers of a list of followers, we often have duplicates.
This adds deduplication and a count for the followers of followers and makes these updates way more efficient.
The cache handlers are generally responsible for adding debug logs to
their methods, see
`packages/next/src/server/lib/cache-handlers/default.ts` for reference.
However, the `'use cache'` wrapper in
`packages/next/src/server/use-cache/use-cache-wrapper.ts` also adds a
few debug logs of its own that pertain to logic that is specific to the
wrapper itself, e.g. when discarding cache entries because of tag
revalidation. With this PR, we're now also logging cache hits and misses
in the Resume Data Cache, as well as when entries are omitted from the
static or runtime shell due to their revalidate, expire or stale values.

Docs:
https://nextjs.org/docs/app/api-reference/directives/use-cache#verbose-logging
## Enhance test documentation with best practices and non-interactive
test generation

### What?
Expanded the AGENTS.md documentation with detailed guidance on writing
tests, including:
- Added non-interactive test generation instructions for AI agents
- Documented best practices for writing tests with code examples
- Provided clear guidance on using `retry()` instead of deprecated
`check()` or `setTimeout`
- Added recommendations for using fixture directories over inline file
definitions
### What?

Add a list of changed defined env vars to the trace file
When [verbose cache
logging](https://nextjs.org/docs/app/guides/incremental-static-regeneration#verifying-correct-production-behavior)
is enabled, we were always adding a debug log as follows after rendering
a page (during prerendering or at request time):

```
pending revalidates promise finished for: {
  auth: null,
  host: null,
  hostname: null,
  pathname: '/',
  port: null,
  protocol: null,
  query: undefined,
  search: '',
  hash: '',
  href: '/',
  slashes: null
}
```

However, if there were no pending revalidates to process, this log is
misleading as it suggests that there were pending revalidates that have
now been processed, while in reality there were none. So with this PR,
we now only log this message if there are actually any pending
revalidates, i.e. some tags were revalidated, a `fetch` cache entry was
revalidated, an `unstable_cache` entry was revalidated, or a `'use
cache'` entry was saved to a cache handler.

In addition, the log is now shortened to only log the URL string instead
of the full URL object for better readability, e.g.:

```
pending revalidates promise finished for: /
```
Release notes: https://github.com/lovell/sharp/releases/tag/v0.34.5

- Upgrade to libvips v8.17.3 for upstream bug fixes.
- Add experimental support for prebuilt Linux RISC-V 64-bit binaries.
- Support building from source with npm v12+
- Add support for BigTIFF output.
- Improve error messaging when only warnings issued.
- Simplify ICC processing when retaining input profiles.
Refactoring/cleanup, no behavioral changes
…#88229)

The transform output for 'use cache' uses `Object.defineProperty` and
`Array.prototype.slice`. In theory, it's possible for a module to shadow
those names and break it:
```ts
// i want to suffer!
const Array = {}
const Object = {}

async function cached() {
  "use cache"
  ...
}
```

We should defensively make sure that our transform's output refers to
the actual Object/Array builtins, not whatever's in scope for that name.
We can do this by using an unresolved syntax context for the
identifiers. This is what we do for `require()` elsewhere:
https://github.com/vercel/next.js/blob/6805af48baf1128e6b2a9e8f1752ee5982f02c60/crates/next-custom-transforms/src/transforms/track_dynamic_imports.rs#L119-L122
Using `quote_ident!(unresolved_ctxt, "Array")` will cause SWC to rename
any local redefinitions of `Array` to something that doesn't clash
(which can be seen in the added snapshots).
Support multi denied_paths in `DiskFileSystem`, it's useful to reduce
redundant task invalidation.
React already disallows javascript URLs. This change extends this
prohibition to Next.js specific APIs that don't serialize to an href on
an anchor tag. There are workarounds if need be but this is considered a
bugfix because these URLs are non-routable and the affected APIs were
never intended to work with these URLs.

This replaces prior efforts here:
vercel#64779 which attempted to make
this capability optional. We decided it was just not supportable and
since workarounds exist the burden of upgrading through this bugfix is
acceptable.

---------

Co-authored-by: Zack Tanner <1939140+ztanner@users.noreply.github.com>
Somewhat surprisingly, no breaking API changes

swc-project/swc@v1.15.5...v1.15.8 tracks the changes
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.
…el#88242)

We may have many `Invalidator`s, and we're often looping over collections of them. Instead of storing a weak reference to `TurboTasksApi` and tokio's `Handle` inside of `Invalidator`, it's better for the callsite to track this.

`Weak<dyn TurboTasksApi>` and `Handle` are both 16-byte fat pointers, and there's some alignment overhead, so **this reduces the size of Invalidator from 40 bytes to 4 bytes** (according to RA), and reduces the number of refcount increment/decrements we have to do when using invalidators.  
  
These changes were LLM-generated, with careful manual review and cleanup.
@lakshit-hivel lakshit-hivel merged commit b933d3d into canary Jan 8, 2026
140 of 339 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.