Repository navigation
fix: fail the build when React reports a render error - #195
Merged
Merged
Conversation
During `vite build`, the RSC render, the SSR prerender and deferred payload renders now get an `onError` handler that logs the error with its source (entry path or defer name) and records it. React recovers from these errors in the output (an `E` row in the RSC payload, a client-rendered Suspense boundary in the HTML), so previously the build wrote the broken page and exited 0. `buildApp` now fails with an error listing every collected error before writing the affected output. Add a `failOnRenderError` option (default `true`); set it to `false` to only log the errors and emit the output as before. Closes #194 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FMU5vtU9xKNCD7XzUNDftA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #194
Summary
React does not stop when a page fails to render. It puts an
Erow in the RSC payload, or with SSR, leaves the affected<Suspense>boundary to render on the client (<!--$!-->). Its defaultonErroronly callsconsole.error. Sovite buildwrote the broken page and exited 0, and a static site has no later request that could fix the page.This PR passes an
onErrorto every render during the build and fails the build when any error is reported.build()insrc/rsc/entry.tsxpassesonErrorto the RSC render of each page: the full tree with SSR on; the shell and the App separately with SSR off. It also passes one torenderHTML, which hands it toprerender. Deferred payloads get one throughsetDeferRenderErrorHandler, andDeferRegistry's render function now receives thedefer()name. Each error is logged with what was being rendered (for exampleRSC payload of "index.html"ordeferred component "Throws") and collected. The dev server is unchanged and keeps React's defaults.buildAppchecks after rendering the deferred payloads and after reading each page, before writing it. If errors were collected, it throws anAggregateErrorthat lists each error and where it happened. The affected pages are not written.failOnRenderError(defaulttrue). Set it tofalseto log the errors and write the output as before.Notes
<Suspense>around the failing part,prerenderalready rejected before this change, so those builds already failed. They still fail withfailOnRenderError: false. The error that ends the build there is React's generic "An error occurred in the Server Components render", but the real error is now logged just above it.browser()API instead, so failing by default doesn't block that pattern.onErrorhook for the user's build module is not included.Tests
e2e/fixture-render-errorwith four cases: no error, a function passed to a Client Component, a deferred component that throws, and a Client Component that throws during SSR. Environment variables choose the case and options, and each variant builds into its owndist/subdirectory.e2e/tests/render-error.spec.ts(Playwright projectrender-error, no web server) runsvite buildfor each case with SSR on and off. It checks the exit code and error message, that noindex.htmlis written on failure, and thatfailOnRenderError: falseproduces theErow and<!--$!-->as before. All 9 tests pass; against the old code, 7 fail (all but the two no-error cases).renderErrors.ts.pnpm test:run,typecheck,lint,format:checkandpnpm build(including docs and example) pass. The existing e2e suites pass: 48 against the production build and 32 against the dev server.Docs
failOnRenderErroroption to thefunstackStatic()API page.<Suspense>also fail the build.Generated by Claude Code