feat: stitch errors with react owner stack
What
When we're using experimental react, we'll leverage React's new experimental API captureOwnerStack to access the owner stack trace and then stitch it with the current error trace from the stack frame react-stack-bottom-frame.
As the API only existed on experimental channel of React, we only enable it when PPR is enabled right now. Could extend to when react experimental is used later. This feature is guard under a flag experimental.reactOwnerStack
Closes NDX-247
Why
In this way we'll provide more helpful stack trace for react errors, and users can easily tell how the error was triggered through the rendered component tree. This will directly help you locate the where error is exactly throwing from.
After Enabling the Flag
Before Enabling the Flag
This stack of pull requests is managed by Graphite. Learn more about stacking.
Join @huozhi and the rest of your teammates on
Graphite
Failing test suites
Commit: e20267b7566a00de85d5f3e94a4f0e304380f83f
pnpm test test/integration/amp-export-validation/test/index.test.js
- AMP Validation on Export > production mode > should have shown errors during build
Expand output
โ AMP Validation on Export โบ production mode โบ should have shown errors during build
expect(received).toMatch(expected)
Expected pattern: /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./
Received string: " โฒ Next.js 15.0.2-canary.0ยท
Checking validity of types ...
Creating an optimized production build ...
โ Compiled successfully
Collecting page data ...
Generating static pages (0/8) ...
Generating static pages (2/8)ยทยท
โ Linting is disabled.
Error occurred prerendering page \"/first\". Read more: https://nextjs.org/docs/messages/prerender-error
AssertionError: Assertion failed: WebAssembly is uninitialized
at new module$contents$goog$asserts_AssertionError (../evalmachine.<anonymous>:102:1441)
at module$contents$goog$asserts_doAssertFailure (../evalmachine.<anonymous>:103:354)
at goog.asserts.assertExists (../evalmachine.<anonymous>:104:374)
at Object.module$contents$amp$validator_validateString [as validateString] (../evalmachine.<anonymous>:2238:108)
at Validator.validateString (../packages/next/dist/compiled/amphtml-validator/index.js:17:2057)
at validateAmp (../packages/next/dist/export/routes/pages.js:92:34)
at async exportPagesPage (../packages/next/dist/export/routes/pages.js:109:13)
at async Span.traceAsyncFn (../packages/next/dist/trace/trace.js:157:20)
at async exportPage (../packages/next/dist/export/worker.js:350:18)
Export encountered an error on /first, exiting the build.
โจฏ Static worker exited with code: 1 and signal: null
"
at Object.toMatch (integration/amp-export-validation/test/index.test.js:28:29)
Read more about building and testing Next.js in contributing.md.
Stats from current PR
Default Build (Increase detected โ ๏ธ)
General Overall increase โ ๏ธ
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| buildDuration | 19.7s | 16.5s | N/A |
| buildDurationCached | 15.4s | 13.5s | N/A |
| nodeModulesSize | 373 MB | 374 MB | โ ๏ธ +97.6 kB |
| nextStartRea..uration (ms) | 414ms | 417ms | N/A |
Client Bundles (main, webpack) Overall increase โ ๏ธ
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| 2585.HASH.js gzip | 169 B | 169 B | โ |
| 7382-HASH.js gzip | 5.27 kB | 5.27 kB | โ |
| 850563de-HASH.js gzip | 52.6 kB | 52.6 kB | N/A |
| 9756-HASH.js gzip | 44.6 kB | 44.9 kB | โ ๏ธ +331 B |
| framework-HASH.js gzip | 57.4 kB | 57.4 kB | N/A |
| main-app-HASH.js gzip | 232 B | 233 B | N/A |
| main-HASH.js gzip | 32.8 kB | 32.9 kB | โ ๏ธ +134 B |
| webpack-HASH.js gzip | 1.71 kB | 1.71 kB | N/A |
| Overall change | 82.8 kB | 83.3 kB | โ ๏ธ +465 B |
Legacy Client Bundles (polyfills)
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| polyfills-HASH.js gzip | 39.4 kB | 39.4 kB | โ |
| Overall change | 39.4 kB | 39.4 kB | โ |
Client Pages
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| _app-HASH.js gzip | 194 B | 194 B | โ |
| _error-HASH.js gzip | 193 B | 192 B | N/A |
| amp-HASH.js gzip | 511 B | 510 B | N/A |
| css-HASH.js gzip | 343 B | 341 B | N/A |
| dynamic-HASH.js gzip | 1.85 kB | 1.84 kB | N/A |
| edge-ssr-HASH.js gzip | 264 B | 266 B | N/A |
| head-HASH.js gzip | 363 B | 361 B | N/A |
| hooks-HASH.js gzip | 392 B | 390 B | N/A |
| image-HASH.js gzip | 4.41 kB | 4.4 kB | N/A |
| index-HASH.js gzip | 268 B | 268 B | โ |
| link-HASH.js gzip | 2.78 kB | 2.78 kB | N/A |
| routerDirect..HASH.js gzip | 329 B | 328 B | N/A |
| script-HASH.js gzip | 395 B | 393 B | N/A |
| withRouter-HASH.js gzip | 324 B | 325 B | N/A |
| 1afbb74e6ecf..834.css gzip | 106 B | 106 B | โ |
| Overall change | 568 B | 568 B | โ |
Client Build Manifests
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 746 B | 750 B | N/A |
| Overall change | 0 B | 0 B | โ |
Rendered Page Sizes
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| index.html gzip | 522 B | 524 B | N/A |
| link.html gzip | 538 B | 538 B | โ |
| withRouter.html gzip | 521 B | 519 B | N/A |
| Overall change | 538 B | 538 B | โ |
Edge SSR bundle Size
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| edge-ssr.js gzip | 128 kB | 128 kB | N/A |
| page.js gzip | 187 kB | 187 kB | N/A |
| Overall change | 0 B | 0 B | โ |
Middleware size
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| middleware-b..fest.js gzip | 673 B | 669 B | N/A |
| middleware-r..fest.js gzip | 155 B | 156 B | N/A |
| middleware.js gzip | 31 kB | 31 kB | N/A |
| edge-runtime..pack.js gzip | 844 B | 844 B | โ |
| Overall change | 844 B | 844 B | โ |
Next Runtimes Overall increase โ ๏ธ
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| 973-experime...dev.js gzip | 322 B | 322 B | โ |
| 973.runtime.dev.js gzip | 314 B | 314 B | โ |
| app-page-exp...dev.js gzip | 317 kB | 317 kB | โ ๏ธ +267 B |
| app-page-exp..prod.js gzip | 121 kB | 121 kB | โ |
| app-page-tur..prod.js gzip | 134 kB | 134 kB | โ |
| app-page-tur..prod.js gzip | 129 kB | 129 kB | โ |
| app-page.run...dev.js gzip | 307 kB | 308 kB | โ ๏ธ +264 B |
| app-page.run..prod.js gzip | 117 kB | 117 kB | โ |
| app-route-ex...dev.js gzip | 35.9 kB | 35.9 kB | โ |
| app-route-ex..prod.js gzip | 24.4 kB | 24.4 kB | โ |
| app-route-tu..prod.js gzip | 24.4 kB | 24.4 kB | โ |
| app-route-tu..prod.js gzip | 24.2 kB | 24.2 kB | โ |
| app-route.ru...dev.js gzip | 37.5 kB | 37.5 kB | โ |
| app-route.ru..prod.js gzip | 24.2 kB | 24.2 kB | โ |
| pages-api-tu..prod.js gzip | 9.61 kB | 9.61 kB | โ |
| pages-api.ru...dev.js gzip | 11.4 kB | 11.4 kB | โ |
| pages-api.ru..prod.js gzip | 9.61 kB | 9.61 kB | โ |
| pages-turbo...prod.js gzip | 20.9 kB | 20.9 kB | โ |
| pages.runtim...dev.js gzip | 26.5 kB | 26.5 kB | โ |
| pages.runtim..prod.js gzip | 20.9 kB | 20.9 kB | โ |
| server.runti..prod.js gzip | 58.4 kB | 58.4 kB | โ |
| Overall change | 1.45 MB | 1.46 MB | โ ๏ธ +531 B |
build cache Overall increase โ ๏ธ
| vercel/next.js canary | vercel/next.js 09-24-apply_stitch_errors | Change | |
|---|---|---|---|
| 0.pack gzip | 1.85 MB | 1.85 MB | โ ๏ธ +195 B |
| index.pack gzip | 144 kB | 143 kB | N/A |
| Overall change | 1.85 MB | 1.85 MB | โ ๏ธ +195 B |
Diff details
Diff for page.js
Diff too large to display
Diff for middleware.js
Diff too large to display
Diff for edge-ssr.js
Diff too large to display
Diff for dynamic-HASH.js
@@ -1,7 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[2739],
{
- /***/ 9725: /***/ (
+ /***/ 1959: /***/ (
__unused_webpack_module,
__unused_webpack_exports,
__webpack_require__
@@ -9,7 +9,7 @@
(window.__NEXT_P = window.__NEXT_P || []).push([
"/dynamic",
function () {
- return __webpack_require__(5425);
+ return __webpack_require__(4291);
},
]);
if (false) {
@@ -18,7 +18,7 @@
/***/
},
- /***/ 4979: /***/ (module, exports, __webpack_require__) => {
+ /***/ 9774: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -51,7 +51,7 @@
__webpack_require__(6609)
);
const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(2158)
+ __webpack_require__(2134)
);
const isServerSide = "object" === "undefined";
// Normalize loader to return the module as form { default: Component } for `React.lazy`.
@@ -152,11 +152,7 @@
/***/
},
- /***/ 9320: /***/ (
- __unused_webpack_module,
- exports,
- __webpack_require__
- ) => {
+ /***/ 81: /***/ (__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
/* __next_internal_client_entry_do_not_use__ cjs */
Object.defineProperty(exports, "__esModule", {
@@ -179,7 +175,7 @@
/***/
},
- /***/ 2158: /***/ (
+ /***/ 2134: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -221,7 +217,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
const _react = /*#__PURE__*/ _interop_require_default._(
__webpack_require__(6609)
);
- const _loadablecontextsharedruntime = __webpack_require__(9320);
+ const _loadablecontextsharedruntime = __webpack_require__(81);
function resolve(obj) {
return obj && obj.default ? obj.default : obj;
}
@@ -456,7 +452,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
/***/
},
- /***/ 5425: /***/ (
+ /***/ 4291: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -471,7 +467,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(4744);
/* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(5937);
+ __webpack_require__(5904);
/* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_dynamic__WEBPACK_IMPORTED_MODULE_1__
@@ -480,12 +476,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
() =>
__webpack_require__
- .e(/* import() */ 2585)
- .then(__webpack_require__.bind(__webpack_require__, 2585))
+ .e(/* import() */ 5860)
+ .then(__webpack_require__.bind(__webpack_require__, 5860))
.then((mod) => mod.Hello),
{
loadableGenerated: {
- webpack: () => [/*require.resolve*/ 2585],
+ webpack: () => [/*require.resolve*/ 5860],
},
}
);
@@ -512,12 +508,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
/***/
},
- /***/ 5937: /***/ (
+ /***/ 5904: /***/ (
module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(4979);
+ module.exports = __webpack_require__(9774);
/***/
},
@@ -527,7 +523,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [2888, 9774, 179], () =>
- __webpack_exec__(9725)
+ __webpack_exec__(1959)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
Diff for image-HASH.js
@@ -1,7 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[8358],
{
- /***/ 32: /***/ (
+ /***/ 6529: /***/ (
__unused_webpack_module,
__unused_webpack_exports,
__webpack_require__
@@ -9,7 +9,7 @@
(window.__NEXT_P = window.__NEXT_P || []).push([
"/image",
function () {
- return __webpack_require__(3299);
+ return __webpack_require__(9636);
},
]);
if (false) {
@@ -18,7 +18,7 @@
/***/
},
- /***/ 9708: /***/ (module, exports, __webpack_require__) => {
+ /***/ 709: /***/ (module, exports, __webpack_require__) => {
"use strict";
/* __next_internal_client_entry_do_not_use__ cjs */
Object.defineProperty(exports, "__esModule", {
@@ -40,17 +40,17 @@
__webpack_require__(610)
);
const _head = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(5136)
+ __webpack_require__(9770)
);
- const _getimgprops = __webpack_require__(8064);
- const _imageconfig = __webpack_require__(538);
- const _imageconfigcontextsharedruntime = __webpack_require__(1780);
- const _warnonce = __webpack_require__(2626);
- const _routercontextsharedruntime = __webpack_require__(5197);
+ const _getimgprops = __webpack_require__(2298);
+ const _imageconfig = __webpack_require__(8401);
+ const _imageconfigcontextsharedruntime = __webpack_require__(947);
+ const _warnonce = __webpack_require__(8761);
+ const _routercontextsharedruntime = __webpack_require__(4785);
const _imageloader = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(3204)
+ __webpack_require__(9836)
);
- const _usemergedref = __webpack_require__(7213);
+ const _usemergedref = __webpack_require__(8647);
// This is replaced by webpack define plugin
const configEnv = {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
@@ -371,7 +371,7 @@
/***/
},
- /***/ 7213: /***/ (module, exports, __webpack_require__) => {
+ /***/ 8647: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -432,7 +432,7 @@
/***/
},
- /***/ 8064: /***/ (
+ /***/ 2298: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -448,9 +448,9 @@
return getImgProps;
},
});
- const _warnonce = __webpack_require__(2626);
- const _imageblursvg = __webpack_require__(7001);
- const _imageconfig = __webpack_require__(538);
+ const _warnonce = __webpack_require__(8761);
+ const _imageblursvg = __webpack_require__(34);
+ const _imageconfig = __webpack_require__(8401);
const VALID_LOADING_VALUES =
/* unused pure expression or super */ null && [
"lazy",
@@ -824,7 +824,7 @@
/***/
},
- /***/ 7001: /***/ (__unused_webpack_module, exports) => {
+ /***/ 34: /***/ (__unused_webpack_module, exports) => {
"use strict";
/**
* A shared function, used on both client and server, to generate a SVG blur placeholder.
@@ -879,7 +879,7 @@
/***/
},
- /***/ 4178: /***/ (
+ /***/ 2933: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -906,10 +906,10 @@
},
});
const _interop_require_default = __webpack_require__(9608);
- const _getimgprops = __webpack_require__(8064);
- const _imagecomponent = __webpack_require__(9708);
+ const _getimgprops = __webpack_require__(2298);
+ const _imagecomponent = __webpack_require__(709);
const _imageloader = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(3204)
+ __webpack_require__(9836)
);
function getImageProps(imgProps) {
const { props } = (0, _getimgprops.getImgProps)(imgProps, {
@@ -941,7 +941,7 @@
/***/
},
- /***/ 3204: /***/ (__unused_webpack_module, exports) => {
+ /***/ 9836: /***/ (__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -976,7 +976,7 @@
/***/
},
- /***/ 3299: /***/ (
+ /***/ 9636: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -993,8 +993,8 @@
// EXTERNAL MODULE: ./node_modules/.pnpm/[email protected]/node_modules/react/jsx-runtime.js
var jsx_runtime = __webpack_require__(4744);
- // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+main-repo+packages+next+next-packed.tgz_react-dom@19.0.0-rc-45804af1-20241021_re_fqnwmzresl2hrinmjfrqg34ihq/node_modules/next/image.js
- var next_image = __webpack_require__(7641);
+ // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+diff-repo+packages+next+next-packed.tgz_react-dom@19.0.0-rc-45804af1-20241021_re_dcrk7anheu5balwwdvbhf3r7h4/node_modules/next/image.js
+ var next_image = __webpack_require__(3415);
var image_default = /*#__PURE__*/ __webpack_require__.n(next_image); // CONCATENATED MODULE: ./pages/nextjs.png
/* harmony default export */ const nextjs = {
src: "/_next/static/media/nextjs.cae0b805.png",
@@ -1024,12 +1024,12 @@
/***/
},
- /***/ 7641: /***/ (
+ /***/ 3415: /***/ (
module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(4178);
+ module.exports = __webpack_require__(2933);
/***/
},
@@ -1039,7 +1039,7 @@
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [2888, 9774, 179], () =>
- __webpack_exec__(32)
+ __webpack_exec__(6529)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
Diff for 9756-HASH.js
Diff too large to display
Diff for main-HASH.js
Diff too large to display
Diff for app-page-exp..ntime.dev.js
Diff too large to display
Diff for app-page.runtime.dev.js
Diff too large to display