Commit Graph

8 Commits

Author SHA1 Message Date
Jiwon Choi 74ce6b2e2f Reapply "Stabilize catchError and retry by removing unstable_ prefix" (#94623)
### What?

Reverts #94617, which had reverted #94610. This re-lands the
stabilization of the `catchError` API and the `retry` error prop by
removing their `unstable_` prefix across source, docs, and tests.

### Why?

#94610 was reverted in #94617 to unblock another change. This re-applies
it now that it is no longer blocked.

### How?

`git revert` of the revert commit. The repo's custom errors.json merge
driver handled the error registry: the original codes `1324`/`1325` had
been reclaimed by `instant` errors after the revert, so the reintroduced
messages were minted as new codes `1360` (`retry()` can only be used in
the App Router) and `1361` (`catchError` can only be used in Client
Components), keeping errors.json append-only.

The docs changelog adds `v16.3.0 | catchError became stable.` while
retaining the historical `v16.2.0 | unstable_catchError introduced.`
row.

### Verification

- `pnpm update-error-codes` (check_error_codes passes; errors.json in
sync)
- `pnpm build` (full JS build, exit 0)
- `pnpm --filter=next types` (exit 0)
- Not run: Rust/cargo build (`react_server_components.rs` change is a
one-line allow-list string revert; left to CI)

<!-- NEXT_JS_LLM_PR -->
2026-06-09 16:11:44 -07:00
Jiwon Choi 3d920355dd Revert "Stabilize catchError and retry by removing unstable_ prefix" (#94617)
Reverts vercel/next.js#94610

Unblock
2026-06-09 19:47:48 +00:00
Jiwon Choi 6b3936a332 Stabilize catchError and retry by removing unstable_ prefix (#94610)
### What?

Promotes two experimental error-handling APIs to stable by dropping the
`unstable_` prefix:

- `unstable_catchError` → `catchError` (exported from `next/error`)
- `unstable_retry` → `retry` (the prop Next.js injects into `error.js` /
`global-error.js` boundaries and `catchError` fallbacks)

### Why?

Both were introduced as `unstable_` in `v16.2.0` and are now stable as
of `v16.3.0`. The experimental prefix should be removed from the stable
surface.

### How?

- Renamed the `next/error` export (`error.d.ts`, `error.js`,
`src/api/error.ts`, `src/api/error.react-server.ts`) and the
implementation in `client/components/catch-error.tsx`.
- Renamed the framework-injected `retry` prop across
`error-boundary.tsx`, `builtin/global-error.tsx`, the dev-overlay error
boundary, and the `ErrorInfo` type.
- Updated the RSC client-only export list in the SWC transform
(`react_server_components.rs`) so importing `catchError` in a Server
Component still produces the "only available in Client Components"
error.
- Updated the thrown error messages and their `errors.json` entries
(codes 1138/1139), the TypeScript-plugin serialization-exemption rule,
all affected tests, the rspack test manifests, and the docs.
- Docs version-history tables keep the historical `unstable_` rows and
add a `v16.3.0` row noting the rename to stable.

This is a clean rename with **no** backward-compatible `unstable_`
alias.

### Verification

- Passed: pre-commit hooks (`prettier`, `eslint --fix`, `rustfmt`) on
all 35 changed files.
- Passed: repo-wide grep confirms no remaining `unstable_catchError` /
`unstable_retry` outside the intended historical version-history rows.
- In progress locally (covered by CI): `pnpm build-all` (native SWC
still compiling on a fresh worktree), then `pnpm --filter=next types`
and the targeted e2e suites (`app-dir/catch-error`, `app-dir/errors`,
`rsc-build-errors`, typescript-plugin `client-boundary`).

<!-- NEXT_JS_LLM_PR -->
2026-06-09 21:05:02 +02:00
Janka Uryga ea541987d1 fix: handling of falsey values in error boundaries (#93134)
our error boundaries had a bunch of logic that set `state.error = error`
and then checked `if (state.error)`, which only works correctly if
thrown value is truthy. it breaks if something does e.g. `throw
undefined`. in this case, we would incorrectly think that no error
occurred and render children again (instead of a fallback), which can
then lead to an infinite loop if the children throw again.

the fix is to wrap the thrown value, so `state.error` is either `null`
(initial/reset) or `{ thrownValue: ... }` if something errored. i
initially considered using a separate `state.hasError` boolean, but
that's a bit annoying to type, and really we want to model this as a
discriminated union, so using a pseudo-Optional thing is nicer.
2026-04-29 17:25:56 +00:00
Jiwon Choi 9d13b676e8 Add unstable_retry() to error.js (#89685)
Extends the error components API to give better control over recovery.
Previously, the `reset()` prop only cleared the error state and
re-rendered the children. However, this only handles a temporary
rendering error.

The error can be due to data fetching or an RSC phase. In these cases,
`reset()` alone is not sufficient. Users would even need to implement
retry logic using `router.refresh()`.

Therefore, this PR adds a new `unstable_retry()` prop that calls
`router.refresh()` and `reset()` within a `startTransition()` to provide
built-in retry logic. This feature is expected to be preferred over the
`reset()` prop. Only the cases where you'd choose `reset()` are when you
have a reason to do a sync reset without loading any new data.

Closes NAR-767
2026-02-26 21:22:27 +01:00
Jiachi Liu f91cdec44d test: migrate rest async api usage in tests (#71663) 2024-10-23 02:36:20 +02:00
Sebastian "Sebbie" Silbermann 94060f2b98 Handle thrown values that aren't Error instances in App router (#71210) 2024-10-13 16:14:08 +02:00
Jiachi Liu 92e4a4b78c Associate server error digest with browser logged one (#61592)
### What

#### Core
This PR respect the error's digest when recieves new error occurred from
server side, and it will be logged into client on production with the
same `digest` property.
If we discover the original RSC error in SSR error handler, retrieve the
original error

#### Tests

* Move the errors related tests from `test/e2e/app-dir/app` to a
separate test suite `test/e2e/app-dir/errors`
* Add a new test case for logging the original RSC error
* Add a new test case for logging the original Server Action error


### Why

This will help associate the `digest` property of the errors logged from
client with the actual generated server errors. Previously they're
different as we might re-compute the digest proper in handler that react
server renderer thinks it's a new error, which causes we have 2
different errors logged on server side, and 1 logged on client side. The
one on client side can associate to the server errors but it's from
react renderer which is not the original error.

Closes NEXT-2094
Fixes #60684
2024-02-06 13:39:12 +01:00