Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stitch errors with owner stack #69432

Draft
wants to merge 7 commits into
base: canary
Choose a base branch
from
Draft

stitch errors with owner stack #69432

wants to merge 7 commits into from

Conversation

huozhi
Copy link
Member

@huozhi huozhi commented Aug 28, 2024

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 (either when taint or dynamicIO is enabled).

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.

Copy link
Member Author

huozhi commented Aug 28, 2024

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @huozhi and the rest of your teammates on Graphite Graphite

@ijjk
Copy link
Member

ijjk commented Aug 28, 2024

Failing test suites

Commit: c60d825

TURBOPACK=1 pnpm test test/integration/app-dir-export/test/dev-custom-dist-dir.test.ts (turbopack)

  • app dir - with output export and custom distDir (next dev) > should render properly
Expand output

● app dir - with output export and custom distDir (next dev) › should render properly

expect(received).toBe(expected) // Object.is equality

Expected: 200
Received: 500

  31 |   it('should render properly', async () => {
  32 |     const res = await fetchViaHTTP(appPort, '/')
> 33 |     expect(res.status).toBe(200)
     |                        ^
  34 |     expect(await res.text()).toContain('Home')
  35 |   })
  36 | })

  at Object.toBe (integration/app-dir-export/test/dev-custom-dist-dir.test.ts:33:24)

Read more about building and testing Next.js in contributing.md.

pnpm test-dev test/development/app-dir/dynamic-error-trace/index.test.ts

  • app dir - dynamic error trace > should show the error trace
Expand output

● app dir - dynamic error trace › should show the error trace

expect(received).toEqual(expected) // deep equality

- Expected  -  9
+ Received  + 15

- app/lib.js (4:13) @ useHeaders
-
+ ./node_modules/.pnpm/file+..+next-repo-82b016281888fc938694f9e6809e81aa8f8551648ab8bc220f4cbcc8841c4903+packages+n_rulf4xgi2ktlrz6wavhe2u3aui/node_modules/next/dist/client/components/patch/patch-console.js:28:11
+ Module not found: Can't resolve './internal/helpers/hydration-error-info'
-   2 |
-   3 | export function Foo() {
- > 4 |   useHeaders()
+   26 |       if (process.env.NODE_ENV !== 'production') {
+   27 |         const { storeHydrationErrorStateFromConsoleArgs } =
+ > 28 |           require('./internal/helpers/hydration-error-info') as typeof import('../react-dev-overlay/internal/helpers/hydration-error-info')
-     |             ^
-   5 |   return 'foo'
-   6 | }
-   7 |
+      |           ^
+   29 |
+   30 |         storeHydrationErrorStateFromConsoleArgs(...args)
+   31 |         handleClientError(error)
+
+ https://nextjs.org/docs/messages/module-not-found
+
+ Import trace for requested module:
+ ./node_modules/.pnpm/file+..+next-repo-82b016281888fc938694f9e6809e81aa8f8551648ab8bc220f4cbcc8841c4903+packages+n_rulf4xgi2ktlrz6wavhe2u3aui/node_modules/next/dist/client/app-bootstrap.js
+ ./node_modules/.pnpm/file+..+next-repo-82b016281888fc938694f9e6809e81aa8f8551648ab8bc220f4cbcc8841c4903+packages+n_rulf4xgi2ktlrz6wavhe2u3aui/node_modules/next/dist/client/app-next-dev.js

  54 |     const codeframe = await getRedboxSource(browser)
  55 |     // TODO(NDX-115): column for "^"" marker is inconsistent between native, Webpack, and Turbopack
> 56 |     expect(codeframe).toEqual(
     |                       ^
  57 |       process.env.TURBOPACK
  58 |         ? outdent`
  59 |             app/lib.js (4:12) @ Foo

  at Object.toEqual (development/app-dir/dynamic-error-trace/index.test.ts:56:23)

Read more about building and testing Next.js in contributing.md.

pnpm test-dev test/development/app-dir/stitching-errors/stitching-errors.test.ts

  • stitching errors > should log stitched error for browser uncaught errors
  • stitching errors > should log stitched error for browser caught errors
  • stitching errors > should log stitched error for SSR errors
Expand output

● stitching errors › should log stitched error for browser uncaught errors

TypeError: Cannot read properties of undefined (reading 'message')

  65 |     const errorLog = logs.find((log) => {
  66 |       return log.message.includes('Error: browser error')
> 67 |     }).message
     |     ^
  68 |
  69 |     if (process.env.TURBOPACK) {
  70 |       expect(normalizeStackTrace(errorLog)).toMatchInlineSnapshot(`

  at Object.<anonymous> (development/app-dir/stitching-errors/stitching-errors.test.ts:67:5)

● stitching errors › should log stitched error for browser uncaught errors

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `stitching errors should log stitched error for browser uncaught errors 1`

- Snapshot  - 12
+ Received  +  0

- useThrowError
- app/browser/uncaught/page.js 
- useErrorHook
- app/browser/uncaught/page.js 
- ReactDevOverlay
- ../src/client/components/react-dev-overlay/app/hot-reloader-client.tsx 
- assetPrefix
- ../src/client/components/app-router.tsx 
- actionQueue
- ../src/client/components/app-router.tsx 
- AppRouter
- ../src/client/app-index.tsx

  46 |       `)
  47 |     } else {
> 48 |       expect(stackFramesContent).toMatchInlineSnapshot(`
     |                                  ^
  49 |         "useThrowError
  50 |         app/browser/uncaught/page.js 
  51 |         useErrorHook

  at Object.toMatchInlineSnapshot (development/app-dir/stitching-errors/stitching-errors.test.ts:48:34)

● stitching errors › should log stitched error for browser caught errors

Expected no Redbox but found one
header: Build Error
Next.js (15.0.0-canary.163)

Failed to compile
description: Failed to compile
source: ./node_modules/.pnpm/next@file+..+next-repo-be2b63b95162265f19840b5f85b77d4c615f3d4c4e89d2a6b86e5e12bc3c3c81+packa_nyowazijtycwvz2rndmjhmjwoi/node_modules/next/dist/client/components/patch/patch-console.js:28:11
Module not found: Can't resolve './internal/helpers/hydration-error-info'
  26 |       if (process.env.NODE_ENV !== 'production') {
  27 |         const { storeHydrationErrorStateFromConsoleArgs } =
> 28 |           require('./internal/helpers/hydration-error-info') as typeof import('../react-dev-overlay/internal/helpers/hydration-error-info')
     |           ^
  29 |
  30 |         storeHydrationErrorStateFromConsoleArgs(...args)
  31 |         handleClientError(error)

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/.pnpm/next@file+..+next-repo-be2b63b95162265f19840b5f85b77d4c615f3d4c4e89d2a6b86e5e12bc3c3c81+packa_nyowazijtycwvz2rndmjhmjwoi/node_modules/next/dist/client/app-bootstrap.js
./node_modules/.pnpm/next@file+..+next-repo-be2b63b95162265f19840b5f85b77d4c615f3d4c4e89d2a6b86e5e12bc3c3c81+packa_nyowazijtycwvz2rndmjhmjwoi/node_modules/next/dist/client/app-next-dev.js

  111 |     const browser = await next.browser('/browser/caught')
  112 |
> 113 |     await assertNoRedbox(browser)
      |     ^
  114 |
  115 |     const logs = await browser.log()
  116 |     const errorLog = logs.find((log) => {

  at Object.<anonymous> (development/app-dir/stitching-errors/stitching-errors.test.ts:113:5)

● stitching errors › should log stitched error for SSR errors

TypeError: Cannot read properties of undefined (reading 'message')

  171 |     const errorLog = logs.find((log) => {
  172 |       return log.message.includes('Error: ssr error')
> 173 |     }).message
      |     ^
  174 |
  175 |     expect(normalizeStackTrace(errorLog)).toMatchInlineSnapshot(`
  176 |       "Error: ssr error

  at Object.<anonymous> (development/app-dir/stitching-errors/stitching-errors.test.ts:173:5)

● stitching errors › should log stitched error for SSR errors

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `stitching errors should log stitched error for SSR errors 1`

- Snapshot  - 12
+ Received  +  0

- useThrowError
- app/ssr/page.js 
- useErrorHook
- app/ssr/page.js 
- ReactDevOverlay
- ../src/client/components/react-dev-overlay/app/hot-reloader-client.tsx 
- assetPrefix
- ../src/client/components/app-router.tsx 
- actionQueue
- ../src/client/components/app-router.tsx 
- AppRouter
- ../src/client/app-index.tsx

  152 |       `)
  153 |     } else {
> 154 |       expect(stackFramesContent).toMatchInlineSnapshot(`
      |                                  ^
  155 |         "useThrowError
  156 |         app/ssr/page.js 
  157 |         useErrorHook

  at Object.toMatchInlineSnapshot (development/app-dir/stitching-errors/stitching-errors.test.ts:154:34)

Read more about building and testing Next.js in contributing.md.

pnpm test-dev test/development/app-dir/dev-fetch-hmr/dev-fetch-hmr.test.ts

  • dev-fetch-hmr > should retain module level fetch patching
Expand output

● dev-fetch-hmr › should retain module level fetch patching