Skip to content

Conversation

gaojude
Copy link
Contributor

@gaojude gaojude commented Oct 5, 2025

No description provided.

@ijjk
Copy link
Member

ijjk commented Oct 5, 2025

Failing test suites

Commit: cfc26b0 | About building and testing Next.js

pnpm test test/integration/development-runtime-config/test/index.test.js

  • should work with runtime-config in next.config.js > empty runtime-config (DD)
  • should work with runtime-config in next.config.js > with runtime-config (DD)
Expand output

● should work with runtime-config in next.config.js › empty runtime-config

FetchError: request to http://localhost:35409/post/1 failed, reason: socket hang up

  at ClientRequest.<anonymous> (../node_modules/.pnpm/node-fetch@2.6.7_encoding@0.1.13/node_modules/node-fetch/lib/index.js:1491:11)

● should work with runtime-config in next.config.js › with runtime-config

FetchError: request to http://localhost:36519/post/1 failed, reason: socket hang up

  at ClientRequest.<anonymous> (../node_modules/.pnpm/node-fetch@2.6.7_encoding@0.1.13/node_modules/node-fetch/lib/index.js:1491:11)

pnpm test test/integration/create-next-app/package-manager/bun.test.ts

  • create-next-app with package manager bun > should use bun for --use-bun flag (DD)
  • create-next-app with package manager bun > should use bun when user-agent is bun (DD)
  • create-next-app with package manager bun > should use bun for --use-bun flag with example (DD)
  • create-next-app with package manager bun > should use bun when user-agent is bun with example (DD)
Expand output

● create-next-app with package manager bun › should use bun for --use-bun flag

Command failed with exit code 217 (Unknown system error -217): npm i -g bun

  25 |     nextTgzFilename = pkgPaths.get('next')
  26 |
> 27 |     await command('bun', ['--version'])
     |     ^
  28 |       // install bun if not available
  29 |       .catch(() => command('npm', ['i', '-g', 'bun']))
  30 |

  at makeError (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/lib/error.js:58:11)
  at handlePromise (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/index.js:112:26)
  at Object.<anonymous> (integration/create-next-app/package-manager/bun.test.ts:27:5)

● create-next-app with package manager bun › should use bun when user-agent is bun

Command failed with exit code 217 (Unknown system error -217): npm i -g bun

  25 |     nextTgzFilename = pkgPaths.get('next')
  26 |
> 27 |     await command('bun', ['--version'])
     |     ^
  28 |       // install bun if not available
  29 |       .catch(() => command('npm', ['i', '-g', 'bun']))
  30 |

  at makeError (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/lib/error.js:58:11)
  at handlePromise (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/index.js:112:26)
  at Object.<anonymous> (integration/create-next-app/package-manager/bun.test.ts:27:5)

● create-next-app with package manager bun › should use bun for --use-bun flag with example

Command failed with exit code 217 (Unknown system error -217): npm i -g bun

  25 |     nextTgzFilename = pkgPaths.get('next')
  26 |
> 27 |     await command('bun', ['--version'])
     |     ^
  28 |       // install bun if not available
  29 |       .catch(() => command('npm', ['i', '-g', 'bun']))
  30 |

  at makeError (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/lib/error.js:58:11)
  at handlePromise (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/index.js:112:26)
  at Object.<anonymous> (integration/create-next-app/package-manager/bun.test.ts:27:5)

● create-next-app with package manager bun › should use bun when user-agent is bun with example

Command failed with exit code 217 (Unknown system error -217): npm i -g bun

  25 |     nextTgzFilename = pkgPaths.get('next')
  26 |
> 27 |     await command('bun', ['--version'])
     |     ^
  28 |       // install bun if not available
  29 |       .catch(() => command('npm', ['i', '-g', 'bun']))
  30 |

  at makeError (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/lib/error.js:58:11)
  at handlePromise (../node_modules/.pnpm/execa@2.0.3/node_modules/execa/index.js:112:26)
  at Object.<anonymous> (integration/create-next-app/package-manager/bun.test.ts:27:5)

pnpm test-dev-experimental test/development/app-dir/hydration-error-count/hydration-error-count.test.ts(Experimental)

  • hydration-error-count > should have correct hydration error count for bad nesting (DD)
  • hydration-error-count > should have correct hydration error count for html diff (DD)
  • hydration-error-count > should display correct hydration info in each hydration error view (DD)
  • hydration-error-count > should display runtime error separately from hydration errors (DD)
Expand output

● hydration-error-count › should have correct hydration error count for bad nesting

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `hydration-error-count should have correct hydration error count for bad nesting 1`

- Snapshot  - 1
+ Received  + 1

@@ -8,11 +8,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/bad-nesting" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="bad-nestin...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <p>
  >                             <p>

   9 |     const browser = await next.browser('/bad-nesting')
  10 |
> 11 |     await expect(browser).toDisplayCollapsedRedbox(`
     |                           ^
  12 |      [
  13 |        {
  14 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/app-dir/hydration-error-count/hydration-error-count.test.ts:11:27)

● hydration-error-count › should have correct hydration error count for html diff

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `hydration-error-count should have correct hydration error count for html diff 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/html-diff" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
-                       <SegmentViewNode type="page" pagePath="html-diff/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
                              <p>
  +                             client

  62 |     const browser = await next.browser('/html-diff')
  63 |
> 64 |     await expect(browser).toDisplayCollapsedRedbox(`
     |                           ^
  65 |      {
  66 |        "componentStack": "...
  67 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/app-dir/hydration-error-count/hydration-error-count.test.ts:64:27)

● hydration-error-count › should display correct hydration info in each hydration error view

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `hydration-error-count should display correct hydration info in each hydration error view 1`

- Snapshot  - 2
+ Received  + 2

@@ -8,11 +8,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/two-issues" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="two-issues...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <p className="client">
  >                             <p>
@@ -40,11 +40,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/two-issues" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="two-issues...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
                              <p
  +                             className="client"

  101 |     const browser = await next.browser('/two-issues')
  102 |
> 103 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  104 |      [
  105 |        {
  106 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/app-dir/hydration-error-count/hydration-error-count.test.ts:103:27)

● hydration-error-count › should display runtime error separately from hydration errors

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `hydration-error-count should display runtime error separately from hydration errors 1`

- Snapshot  - 1
+ Received  + 1

@@ -8,11 +8,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/hydration..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="hydration-...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <p>
  >                             <p>

  175 |     const browser = await next.browser('/hydration-with-runtime-errors')
  176 |
> 177 |     await expect(browser).toDisplayRedbox(`
      |                           ^
  178 |      [
  179 |        {
  180 |          "componentStack": "...

  at Object.toDisplayRedbox (development/app-dir/hydration-error-count/hydration-error-count.test.ts:177:27)

pnpm test-dev-experimental test/development/app-dir/segment-explorer-globals/segment-explorer-globals.test.ts(Experimental)

  • segment-explorer - globals > should show global-error segment (DD)
  • segment-explorer - globals > should display parallel routes default page when present (DD)
Expand output

● segment-explorer - globals › should show global-error segment

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer - globals should show global-error segment 1`

Snapshot: "app/ [global-error.tsx]"
Received: "/  / tmp / next-install-9ad81ef32df5829c5139dfcae37d5ecc5b618689e95232028fb59a79a1edffe7 / app/ [global-error.tsx]"

   9 |   it('should show global-error segment', async () => {
  10 |     const browser = await next.browser('/runtime-error')
> 11 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(
     |                                                      ^
  12 |       `"app/ [global-error.tsx]"`
  13 |     )
  14 |   })

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer-globals/segment-explorer-globals.test.ts:11:54)

● segment-explorer - globals › should display parallel routes default page when present

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer - globals should display parallel routes default page when present 1`

Snapshot: "app/ [global-not-found.tsx]"
Received: "/  / tmp / next-install-9ad81ef32df5829c5139dfcae37d5ecc5b618689e95232028fb59a79a1edffe7 / app/ [global-not-found.tsx]"

  16 |   it('should display parallel routes default page when present', async () => {
  17 |     const browser = await next.browser('/404-not-found')
> 18 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(
     |                                                      ^
  19 |       `"app/ [global-not-found.tsx]"`
  20 |     )
  21 |   })

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer-globals/segment-explorer-globals.test.ts:18:54)

pnpm test-dev test/development/acceptance-app/hydration-error.test.ts

  • Error overlay for hydration errors in App router > should show correct hydration error when client and server render different text (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when client renders an extra element (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when extra attributes set on server (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when client renders an extra text node (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when server renders an extra element (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when server renders an extra text node (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when server renders an extra text node in an invalid place (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when server renders an extra whitespace in an invalid place (DD)
  • Error overlay for hydration errors in App router > should show correct hydration error when client renders an extra node inside Suspense content (DD)
  • Error overlay for hydration errors in App router > should only show one hydration error when bad nesting happened - p under p (DD)
  • Error overlay for hydration errors in App router > should only show one hydration error when bad nesting happened - div under p (DD)
  • Error overlay for hydration errors in App router > should only show one hydration error when bad nesting happened - div > tr (DD)
  • Error overlay for hydration errors in App router > should show the highlighted bad nesting html snippet when bad nesting happened (DD)
  • Error overlay for hydration errors in App router > should show error if script is directly placed under html instead of body (DD)
Expand output

● Error overlay for hydration errors in App router › should show correct hydration error when client and server render different text

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when client and server render different text 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/text-mism..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Mismatch} searchParams={{}} params={{}}>
                            <Mismatch params={Promise} searchParams={Promise}>
                              <div className="parent">
                                <main className="child">

  39 |     const browser = await next.browser('/text-mismatch')
  40 |
> 41 |     await expect(browser).toDisplayCollapsedRedbox(`
     |                           ^
  42 |      {
  43 |        "componentStack": "...
  44 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:41:27)

● Error overlay for hydration errors in App router › should show correct hydration error when client renders an extra element

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when client renders an extra element 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/extra-ele..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Mismatch} searchParams={{}} params={{}}>
                            <Mismatch params={Promise} searchParams={Promise}>
                              <div className="parent">
  +                             <main className="only">

  101 |     const browser = await next.browser('/extra-element-client')
  102 |
> 103 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  104 |      {
  105 |        "componentStack": "...
  106 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:103:27)

● Error overlay for hydration errors in App router › should show correct hydration error when extra attributes set on server

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when extra attributes set on server 1`

- Snapshot  - 1
+ Received  + 1

@@ -8,11 +8,11 @@
                <HTTPAccessFallbackBoundary notFound={<SegmentViewNode>} forbidden={undefined} unauthorized={undefined}>
                  <HTTPAccessFallbackErrorBoundary pathname="/extra-att..." notFound={<SegmentViewNode>} ...>
                    <RedirectBoundary>
                      <RedirectErrorBoundary router={{...}}>
                        <InnerLayoutRouter url="/extra-att..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                         <SegmentViewNode type="layout" pagePath="(extra-att...">
+                         <SegmentViewNode type="layout" pagePath="/tmp/next-...">
                            <SegmentTrieNode>
                            <ClientSegmentRoot Component={function Root} slots={{...}} params={{}}>
                              <Root params={Promise}>
                                <html
  -                               className="server-html"

  177 |       `)
  178 |     } else {
> 179 |       await expect(browser).toDisplayCollapsedRedbox(`
      |                             ^
  180 |        {
  181 |          "componentStack": "...
  182 |            <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:179:29)

● Error overlay for hydration errors in App router › should show correct hydration error when client renders an extra text node

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when client renders an extra text node 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/extra-tex..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Mismatch} searchParams={{}} params={{}}>
                            <Mismatch params={Promise} searchParams={Promise}>
                              <div className="parent">
                                <header>

  217 |     const browser = await next.browser('/extra-text-node-client')
  218 |
> 219 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  220 |      {
  221 |        "componentStack": "...
  222 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:219:27)

● Error overlay for hydration errors in App router › should show correct hydration error when server renders an extra element

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when server renders an extra element 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/extra-ele..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Mismatch} searchParams={{}} params={{}}>
                            <Mismatch params={Promise} searchParams={Promise}>
                              <div className="parent">
  -                             <main className="only">

  258 |     const browser = await next.browser('/extra-element-server')
  259 |
> 260 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  261 |      {
  262 |        "componentStack": "...
  263 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:260:27)

● Error overlay for hydration errors in App router › should show correct hydration error when server renders an extra text node

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when server renders an extra text node 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/extra-tex..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Mismatch} searchParams={{}} params={{}}>
                            <Mismatch params={Promise} searchParams={Promise}>
                              <div className="parent">
  -                             only

  296 |     const browser = await next.browser('/extra-text-node-server')
  297 |
> 298 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  299 |      {
  300 |        "componentStack": "...
  301 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:298:27)

● Error overlay for hydration errors in App router › should show correct hydration error when server renders an extra text node in an invalid place

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when server renders an extra text node in an invalid place 1`

- Snapshot  - 2
+ Received  + 2

@@ -7,11 +7,11 @@
            <LoadingBoundary loading={null}>
              <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                <RedirectBoundary>
                  <RedirectErrorBoundary router={{...}}>
                    <InnerLayoutRouter url="/extra-tex..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                     <SegmentViewNode type="page" pagePath="(default)/...">
+                     <SegmentViewNode type="page" pagePath="/tmp/next-...">
                        <SegmentTrieNode>
                        <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                          <Page params={Promise} searchParams={Promise}>
                            <table>
                              <tbody>
@@ -41,11 +41,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/extra-tex..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  +                           <table>
  -                           test

  338 |     })
  339 |
> 340 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  341 |      [
  342 |        {
  343 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:340:27)

● Error overlay for hydration errors in App router › should show correct hydration error when server renders an extra whitespace in an invalid place

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when server renders an extra whitespace in an invalid place 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/extra-whi..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <table>
  >                             {" "}

  411 |     const browser = await next.browser('/extra-whitespace-invalid-place')
  412 |
> 413 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  414 |      {
  415 |        "componentStack": "...
  416 |          <RenderFromTemplateContext>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:413:27)

● Error overlay for hydration errors in App router › should show correct hydration error when client renders an extra node inside Suspense content

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show correct hydration error when client renders an extra node inside Suspense content 1`

- Snapshot  - 1
+ Received  + 1

@@ -5,11 +5,11 @@
          <LoadingBoundary loading={null}>
            <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
              <RedirectBoundary>
                <RedirectErrorBoundary router={{...}}>
                  <InnerLayoutRouter url="/extra-nod..." tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
-                   <SegmentViewNode type="page" pagePath="(default)/...">
+                   <SegmentViewNode type="page" pagePath="/tmp/next-...">
                      <SegmentTrieNode>
                      <ClientPageRoot Component={function Mismatch} searchParams={{}} params={{}}>
                        <Mismatch params={Promise} searchParams={Promise}>
                          <div className="parent">
                            <Suspense fallback={<p>}>

  451 |     const browser = await next.browser('/extra-node-suspense')
  452 |
> 453 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  454 |      {
  455 |        "componentStack": "...
  456 |          <InnerScrollAndFocusHandler segmentPath={[...]} focusAndScrollRef={{apply:false, ...}}>

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:453:27)

● Error overlay for hydration errors in App router › should only show one hydration error when bad nesting happened - p under p

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should only show one hydration error when bad nesting happened - p under p 1`

- Snapshot  - 1
+ Received  + 1

@@ -8,11 +8,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/p-under-p" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <p>
  >                             <p>

  505 |     })
  506 |
> 507 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  508 |      [
  509 |        {
  510 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:507:27)

● Error overlay for hydration errors in App router › should only show one hydration error when bad nesting happened - div under p

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should only show one hydration error when bad nesting happened - div under p 1`

- Snapshot  - 1
+ Received  + 1

@@ -7,11 +7,11 @@
            <LoadingBoundary loading={null}>
              <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                <RedirectBoundary>
                  <RedirectErrorBoundary router={{...}}>
                    <InnerLayoutRouter url="/div-under-p" tree={[...]} cacheNode={{lazyData:null, ...}} segmentPath={[...]}>
-                     <SegmentViewNode type="page" pagePath="(default)/...">
+                     <SegmentViewNode type="page" pagePath="/tmp/next-...">
                        <SegmentTrieNode>
                        <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                          <Page params={Promise} searchParams={Promise}>
                            <div>
                              <div>

  562 |     })
  563 |
> 564 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  565 |      [
  566 |        {
  567 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:564:27)

● Error overlay for hydration errors in App router › should only show one hydration error when bad nesting happened - div > tr

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should only show one hydration error when bad nesting happened - div > tr 1`

- Snapshot  - 1
+ Received  + 1

@@ -8,11 +8,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/tr-under-div" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <div>
  >                             <tr>

  620 |     })
  621 |
> 622 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  623 |      [
  624 |        {
  625 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:622:27)

● Error overlay for hydration errors in App router › should show the highlighted bad nesting html snippet when bad nesting happened

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show the highlighted bad nesting html snippet when bad nesting happened 1`

- Snapshot  - 1
+ Received  + 1

@@ -8,11 +8,11 @@
              <LoadingBoundary loading={null}>
                <HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
                  <RedirectBoundary>
                    <RedirectErrorBoundary router={{...}}>
                      <InnerLayoutRouter url="/bad-nesting" tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                       <SegmentViewNode type="page" pagePath="(default)/...">
+                       <SegmentViewNode type="page" pagePath="/tmp/next-...">
                          <SegmentTrieNode>
                          <ClientPageRoot Component={function Page} searchParams={{}} params={{}}>
                            <Page params={Promise} searchParams={Promise}>
  >                           <p>
                                <span>

  677 |     })
  678 |
> 679 |     await expect(browser).toDisplayCollapsedRedbox(`
      |                           ^
  680 |      [
  681 |        {
  682 |          "componentStack": "...

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:679:27)

● Error overlay for hydration errors in App router › should show error if script is directly placed under html instead of body

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `Error overlay for hydration errors in App router should show error if script is directly placed under html instead of body 1`

- Snapshot  - 1
+ Received  + 1

@@ -20,11 +20,11 @@
                <HTTPAccessFallbackBoundary notFound={<SegmentViewNode>} forbidden={undefined} unauthorized={undefined}>
                  <HTTPAccessFallbackErrorBoundary pathname="/script-un..." notFound={<SegmentViewNode>} ...>
                    <RedirectBoundary>
                      <RedirectErrorBoundary router={{...}}>
                        <InnerLayoutRouter url="/script-un..." tree={[...]} cacheNode={{lazyData:null, ...}} ...>
-                         <SegmentViewNode type="layout" pagePath="(script-un...">
+                         <SegmentViewNode type="layout" pagePath="/tmp/next-...">
                            <SegmentTrieNode>
                            <Root>
  >                           <html>
                                <body>
                                <Script src="https://ex..." strategy="beforeInte...">

  951 |         `)
  952 |       } else {
> 953 |         await expect(browser).toDisplayCollapsedRedbox(`
      |                               ^
  954 |          [
  955 |            {
  956 |              "description": "Cannot render a sync or defer <script> outside the main document without knowing its order. Try adding async="" or moving it into the root <head> tag.",

  at Object.toDisplayCollapsedRedbox (development/acceptance-app/hydration-error.test.ts:953:31)

pnpm test-dev test/development/app-dir/segment-explorer/segment-explorer.test.ts

  • segment-explorer > should render the segment explorer for parallel routes (DD)
  • segment-explorer > should render the segment explorer for parallel routes in edge runtime (DD)
  • segment-explorer > should render the segment explorer for nested routes (DD)
  • segment-explorer > should cleanup on soft navigation (DD)
  • segment-explorer > should handle show file segments in order (DD)
  • segment-explorer > should handle special built-in not-found segments (DD)
  • segment-explorer > should show navigation boundaries of the segment (DD)
  • segment-explorer > should show the loading boundary when it is present (DD)
  • segment-explorer > should show the custom error boundary when present (DD)
  • segment-explorer > should display parallel routes default page when present (DD)
  • segment-explorer > should display boundary selector when a segment has only boundary files (DD)
  • segment-explorer > should render route for index page (DD)
Expand output

● segment-explorer › should render the segment explorer for parallel routes

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should render the segment explorer for parallel routes 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  parallel-routes/ [layout.tsx, page.tsx]
  @bar/ [layout.tsx, page.tsx]
  @foo/ [layout.tsx, page.tsx]

  13 |   it('should render the segment explorer for parallel routes', async () => {
  14 |     const browser = await next.browser('/parallel-routes')
> 15 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
     |                                                      ^
  16 |      "app/ [layout.tsx]
  17 |      parallel-routes/ [layout.tsx, page.tsx]
  18 |      @bar/ [layout.tsx, page.tsx]

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:15:54)

● segment-explorer › should render the segment explorer for parallel routes in edge runtime

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should render the segment explorer for parallel routes in edge runtime 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  parallel-routes-edge/ [layout.tsx, page.tsx]
  @bar/ [layout.tsx, page.tsx]
  @foo/ [layout.tsx, page.tsx]

  24 |   it('should render the segment explorer for parallel routes in edge runtime', async () => {
  25 |     const browser = await next.browser('/parallel-routes-edge')
> 26 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
     |                                                      ^
  27 |      "app/ [layout.tsx]
  28 |      parallel-routes-edge/ [layout.tsx, page.tsx]
  29 |      @bar/ [layout.tsx, page.tsx]

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:26:54)

● segment-explorer › should render the segment explorer for nested routes

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should render the segment explorer for nested routes 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  (v2)/ [layout.tsx]
  blog / (team)/ [layout.tsx, template.tsx]
  ~ / (overview)/ [layout.tsx]
  grid/ [page.tsx]

  35 |   it('should render the segment explorer for nested routes', async () => {
  36 |     const browser = await next.browser('/blog/~/grid')
> 37 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
     |                                                      ^
  38 |      "app/ [layout.tsx]
  39 |      (v2)/ [layout.tsx]
  40 |      blog / (team)/ [layout.tsx, template.tsx]

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:37:54)

● segment-explorer › should cleanup on soft navigation

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should cleanup on soft navigation 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  soft-navigation / a/ [page.tsx]

  47 |   it('should cleanup on soft navigation', async () => {
  48 |     const browser = await next.browser('/soft-navigation/a')
> 49 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
     |                                                      ^
  50 |      "app/ [layout.tsx]
  51 |      soft-navigation / a/ [page.tsx]"
  52 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:49:54)

● segment-explorer › should cleanup on soft navigation

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should cleanup on soft navigation 2`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  soft-navigation / b/ [page.tsx]

  58 |     })
  59 |
> 60 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
     |                                                      ^
  61 |      "app/ [layout.tsx]
  62 |      soft-navigation / b/ [page.tsx]"
  63 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:60:54)

● segment-explorer › should handle show file segments in order

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should handle show file segments in order 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  (all) / file-segments/ [layout.tsx, template.tsx, page.tsx]

  67 |   it('should handle show file segments in order', async () => {
  68 |     const browser = await next.browser('/file-segments')
> 69 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
     |                                                      ^
  70 |      "app/ [layout.tsx]
  71 |      (all) / file-segments/ [layout.tsx, template.tsx, page.tsx]"
  72 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:69:54)

● segment-explorer › should handle special built-in not-found segments

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should handle special built-in not-found segments 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx, not-found.js]
+ app/ [not-found.js]
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]

  81 |   it('should handle special built-in not-found segments', async () => {
  82 |     const browser = await next.browser('/404')
> 83 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(
     |                                                      ^
  84 |       `"app/ [layout.tsx, not-found.js]"`
  85 |     )
  86 |     expect(await getSegmentExplorerRoute(browser)).toBe('/404')

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:83:54)

● segment-explorer › should show navigation boundaries of the segment

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should show navigation boundaries of the segment 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  boundary/ [layout.tsx, not-found.tsx]

   98 |   it('should show navigation boundaries of the segment', async () => {
   99 |     const browser = await next.browser('/boundary?name=not-found')
> 100 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  101 |      "app/ [layout.tsx]
  102 |      boundary/ [layout.tsx, not-found.tsx]"
  103 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:100:54)

● segment-explorer › should show navigation boundaries of the segment

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should show navigation boundaries of the segment 2`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  boundary/ [layout.tsx, forbidden.tsx]

  107 |
  108 |     await browser.loadPage(`${next.url}/boundary?name=forbidden`)
> 109 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  110 |      "app/ [layout.tsx]
  111 |      boundary/ [layout.tsx, forbidden.tsx]"
  112 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:109:54)

● segment-explorer › should show navigation boundaries of the segment

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should show navigation boundaries of the segment 3`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  boundary/ [layout.tsx, unauthorized.tsx]

  113 |
  114 |     await browser.loadPage(`${next.url}/boundary?name=unauthorized`)
> 115 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  116 |      "app/ [layout.tsx]
  117 |      boundary/ [layout.tsx, unauthorized.tsx]"
  118 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:115:54)

● segment-explorer › should show the loading boundary when it is present

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should show the loading boundary when it is present 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  search/ [layout.tsx, loading.tsx]

  129 |     })
  130 |
> 131 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  132 |      "app/ [layout.tsx]
  133 |      search/ [layout.tsx, loading.tsx]"
  134 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:131:54)

● segment-explorer › should show the custom error boundary when present

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should show the custom error boundary when present 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  runtime-error / boundary/ [error.tsx]

  138 |   it('should show the custom error boundary when present', async () => {
  139 |     const browser = await next.browser('/runtime-error/boundary')
> 140 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  141 |      "app/ [layout.tsx]
  142 |      runtime-error / boundary/ [error.tsx]"
  143 |     `)

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:140:54)

● segment-explorer › should display parallel routes default page when present

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should display parallel routes default page when present 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  parallel-default/ [layout.tsx, default.tsx]
  @bar/ [layout.tsx]
  subroute/ [page.tsx]
  @foo/ [default.tsx]

  149 |   it('should display parallel routes default page when present', async () => {
  150 |     const browser = await next.browser('/parallel-default/subroute')
> 151 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  152 |      "app/ [layout.tsx]
  153 |      parallel-default/ [layout.tsx, default.tsx]
  154 |      @bar/ [layout.tsx]

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:151:54)

● segment-explorer › should display boundary selector when a segment has only boundary files

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should display boundary selector when a segment has only boundary files 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx]
  no-layout/ []
  framework/ [layout.tsx]
  blog/ [layout.tsx, page.tsx]

  163 |   it('should display boundary selector when a segment has only boundary files', async () => {
  164 |     const browser = await next.browser('/no-layout/framework/blog')
> 165 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
      |                                                      ^
  166 |      "app/ [layout.tsx]
  167 |      no-layout/ []
  168 |      framework/ [layout.tsx]

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:165:54)

● segment-explorer › should render route for index page

expect(received).toMatchInlineSnapshot(snapshot)

Snapshot name: `segment-explorer should render route for index page 1`

- Snapshot  - 1
+ Received  + 2

- app/ [layout.tsx, page.tsx]
+ app/ []
+ / tmp / next-install-43d9e9391f5996f95043dd9c136aa55a12d936fac76f37084e57c7451920819b / app/ [layout.tsx, page.tsx]

  176 |   it('should render route for index page', async () => {
  177 |     const browser = await next.browser('/')
> 178 |     expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(
      |                                                      ^
  179 |       `"app/ [layout.tsx, page.tsx]"`
  180 |     )
  181 |     expect(await getSegmentExplorerRoute(browser)).toBe('/')

  at Object.toMatchInlineSnapshot (development/app-dir/segment-explorer/segment-explorer.test.ts:178:54)

@ijjk
Copy link
Member

ijjk commented Oct 5, 2025

Stats from current PR

Default Build (Increase detected ⚠️)
General
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
buildDuration 18s 15.1s N/A
buildDurationCached 14.2s 11.4s N/A
nodeModulesSize 448 MB 447 MB N/A
nextStartRea..uration (ms) 702ms 715ms N/A
Client Bundles (main, webpack)
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
1916.HASH.js gzip 169 B 169 B
7322-HASH.js gzip 46 kB 45.8 kB N/A
9225-HASH.js gzip 5.19 kB 5.18 kB N/A
c57d0559-HASH.js gzip 55 kB 55 kB N/A
framework-HASH.js gzip 59.8 kB 59.8 kB
main-app-HASH.js gzip 260 B 261 B N/A
main-HASH.js gzip 36.4 kB 36.3 kB N/A
webpack-HASH.js gzip 1.69 kB 1.69 kB N/A
Overall change 60 kB 60 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp 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 jude/devtools-api-and-mcp Change
_app-HASH.js gzip 193 B 193 B
_error-HASH.js gzip 182 B 182 B
css-HASH.js gzip 334 B 334 B
dynamic-HASH.js gzip 1.8 kB 1.79 kB N/A
edge-ssr-HASH.js gzip 256 B 255 B N/A
head-HASH.js gzip 350 B 352 B N/A
hooks-HASH.js gzip 384 B 381 B N/A
image-HASH.js gzip 4.67 kB 4.66 kB N/A
index-HASH.js gzip 259 B 260 B N/A
link-HASH.js gzip 2.28 kB 2.28 kB N/A
routerDirect..HASH.js gzip 318 B 317 B N/A
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 315 B 315 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Overall change 1.52 kB 1.52 kB
Client Build Manifests
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
_buildManifest.js gzip 716 B 719 B N/A
Overall change 0 B 0 B
Rendered Page Sizes
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
index.html gzip 523 B 522 B N/A
link.html gzip 536 B 537 B N/A
withRouter.html gzip 519 B 518 B N/A
Overall change 0 B 0 B
Edge SSR bundle Size Overall increase ⚠️
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
edge-ssr.js gzip 129 kB 129 kB N/A
page.js gzip 242 kB 243 kB ⚠️ +568 B
Overall change 242 kB 243 kB ⚠️ +568 B
Middleware size
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
middleware-b..fest.js gzip 635 B 639 B N/A
middleware-r..fest.js gzip 156 B 157 B N/A
middleware.js gzip 33.1 kB 32.8 kB N/A
edge-runtime..pack.js gzip 846 B 846 B
Overall change 846 B 846 B
Next Runtimes
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
app-page-exp...dev.js gzip 288 kB 288 kB N/A
app-page-exp..prod.js gzip 158 kB 158 kB N/A
app-page-tur...dev.js gzip 288 kB 288 kB N/A
app-page-tur..prod.js gzip 158 kB 158 kB N/A
app-page-tur...dev.js gzip 282 kB 282 kB N/A
app-page-tur..prod.js gzip 154 kB 154 kB N/A
app-page.run...dev.js gzip 282 kB 282 kB N/A
app-page.run..prod.js gzip 154 kB 154 kB N/A
app-route-ex...dev.js gzip 70.1 kB 70.1 kB
app-route-ex..prod.js gzip 49.3 kB 49.3 kB
app-route-tu...dev.js gzip 70.1 kB 70.1 kB
app-route-tu..prod.js gzip 49.3 kB 49.3 kB
app-route-tu...dev.js gzip 69.5 kB 69.5 kB
app-route-tu..prod.js gzip 49 kB 49 kB
app-route.ru...dev.js gzip 69.5 kB 69.5 kB
app-route.ru..prod.js gzip 48.9 kB 48.9 kB
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 328 B 328 B
dist_client_...dev.js gzip 320 B 320 B
dist_client_...dev.js gzip 318 B 318 B
pages-api-tu...dev.js gzip 43.1 kB 43.1 kB
pages-api-tu..prod.js gzip 33.1 kB 33.1 kB
pages-api.ru...dev.js gzip 43 kB 43 kB
pages-api.ru..prod.js gzip 33.1 kB 33.1 kB
pages-turbo....dev.js gzip 52.8 kB 52.8 kB
pages-turbo...prod.js gzip 40.2 kB 40.2 kB
pages.runtim...dev.js gzip 52.8 kB 52.8 kB
pages.runtim..prod.js gzip 40.2 kB 40.2 kB
server.runti..prod.js gzip 78.3 kB 78.3 kB
Overall change 894 kB 894 kB
build cache Overall increase ⚠️
vercel/next.js canary vercel/next.js jude/devtools-api-and-mcp Change
0.pack gzip 3.07 MB 3.08 MB ⚠️ +8.39 kB
index.pack gzip 92.5 kB 92.5 kB N/A
Overall change 3.07 MB 3.08 MB ⚠️ +8.39 kB
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
failed to diff
Diff for css-HASH.js
@@ -1,7 +1,31 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9813],
   {
-    /***/ 3593: /***/ (
+    /***/ 5832: /***/ (module) => {
+      // extracted by mini-css-extract-plugin
+      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
+
+      /***/
+    },
+
+    /***/ 6471: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/css",
+        function () {
+          return __webpack_require__(7839);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 7839: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -15,7 +39,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(1503);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(7634);
+        __webpack_require__(5832);
       /* harmony import */ var _css_module_css__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           _css_module_css__WEBPACK_IMPORTED_MODULE_1__
@@ -34,37 +58,13 @@
 
       /***/
     },
-
-    /***/ 4569: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/css",
-        function () {
-          return __webpack_require__(3593);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 7634: /***/ (module) => {
-      // extracted by mini-css-extract-plugin
-      module.exports = { helloWorld: "css_helloWorld__aUdUq" };
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(4569)
+      __webpack_exec__(6471)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for dynamic-HASH.js
@@ -1,24 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [2291],
   {
-    /***/ 1033: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/dynamic",
-        function () {
-          return __webpack_require__(2283);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 2283: /***/ (
+    /***/ 133: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -33,7 +16,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(1503);
       /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(4939);
+        __webpack_require__(7514);
       /* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_dynamic__WEBPACK_IMPORTED_MODULE_1__
@@ -42,12 +25,12 @@
       const DynamicHello = next_dynamic__WEBPACK_IMPORTED_MODULE_1___default()(
         () =>
           __webpack_require__
-            .e(/* import() */ 1916)
-            .then(__webpack_require__.bind(__webpack_require__, 1916))
+            .e(/* import() */ 3862)
+            .then(__webpack_require__.bind(__webpack_require__, 3862))
             .then((mod) => mod.Hello),
         {
           loadableGenerated: {
-            webpack: () => [/*require.resolve*/ 1916],
+            webpack: () => [/*require.resolve*/ 3862],
           },
         }
       );
@@ -74,17 +57,24 @@
       /***/
     },
 
-    /***/ 4939: /***/ (
-      module,
+    /***/ 431: /***/ (
+      __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(5121);
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/dynamic",
+        function () {
+          return __webpack_require__(133);
+        },
+      ]);
+      if (false) {
+      }
 
       /***/
     },
 
-    /***/ 5121: /***/ (module, exports, __webpack_require__) => {
+    /***/ 1709: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -117,7 +107,7 @@
         __webpack_require__(2223)
       );
       const _loadablesharedruntime = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(7622)
+        __webpack_require__(2522)
       );
       const isServerSide = "object" === "undefined";
       // Normalize loader to return the module as form { default: Component } for `React.lazy`.
@@ -217,34 +207,7 @@
       /***/
     },
 
-    /***/ 5160: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      "use strict";
-      /* __next_internal_client_entry_do_not_use__  cjs */
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "LoadableContext", {
-        enumerable: true,
-        get: function () {
-          return LoadableContext;
-        },
-      });
-      const _interop_require_default = __webpack_require__(1532);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(2223)
-      );
-      const LoadableContext = _react.default.createContext(null);
-      if (false) {
-      } //# sourceMappingURL=loadable-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 7622: /***/ (
+    /***/ 2522: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -286,7 +249,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
       const _react = /*#__PURE__*/ _interop_require_default._(
         __webpack_require__(2223)
       );
-      const _loadablecontextsharedruntime = __webpack_require__(5160);
+      const _loadablecontextsharedruntime = __webpack_require__(4844);
       function resolve(obj) {
         return obj && obj.default ? obj.default : obj;
       }
@@ -519,13 +482,50 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
 
       /***/
     },
+
+    /***/ 4844: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      "use strict";
+      /* __next_internal_client_entry_do_not_use__  cjs */
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "LoadableContext", {
+        enumerable: true,
+        get: function () {
+          return LoadableContext;
+        },
+      });
+      const _interop_require_default = __webpack_require__(1532);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(2223)
+      );
+      const LoadableContext = _react.default.createContext(null);
+      if (false) {
+      } //# sourceMappingURL=loadable-context.shared-runtime.js.map
+
+      /***/
+    },
+
+    /***/ 7514: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(1709);
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(1033)
+      __webpack_exec__(431)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for hooks-HASH.js
@@ -1,24 +1,7 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [9804],
   {
-    /***/ 1679: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/hooks",
-        function () {
-          return __webpack_require__(9198);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 9198: /***/ (
+    /***/ 2592: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -76,13 +59,30 @@
 
       /***/
     },
+
+    /***/ 3925: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/hooks",
+        function () {
+          return __webpack_require__(2592);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(1679)
+      __webpack_exec__(3925)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for image-HASH.js

Diff too large to display

Diff for index-HASH.js
@@ -1,7 +1,24 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [3332],
   {
-    /***/ 3454: /***/ (
+    /***/ 8431: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/",
+        function () {
+          return __webpack_require__(8972);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 8972: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -19,30 +36,13 @@
 
       /***/
     },
-
-    /***/ 9241: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/",
-        function () {
-          return __webpack_require__(3454);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(9241)
+      __webpack_exec__(8431)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for link-HASH.js
@@ -1,7 +1,24 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [4672],
   {
-    /***/ 3262: /***/ (module, exports, __webpack_require__) => {
+    /***/ 2025: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/link",
+        function () {
+          return __webpack_require__(3072);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 3066: /***/ (module, exports, __webpack_require__) => {
       "use strict";
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
@@ -28,16 +45,16 @@
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
         __webpack_require__(2223)
       );
-      const _resolvehref = __webpack_require__(7868);
-      const _islocalurl = __webpack_require__(9350);
-      const _formaturl = __webpack_require__(6319);
-      const _utils = __webpack_require__(9889);
-      const _addlocale = __webpack_require__(9466);
-      const _routercontextsharedruntime = __webpack_require__(5691);
-      const _useintersection = __webpack_require__(3981);
-      const _getdomainlocale = __webpack_require__(4206);
-      const _addbasepath = __webpack_require__(9339);
-      const _usemergedref = __webpack_require__(6848);
+      const _resolvehref = __webpack_require__(2776);
+      const _islocalurl = __webpack_require__(5770);
+      const _formaturl = __webpack_require__(8531);
+      const _utils = __webpack_require__(3565);
+      const _addlocale = __webpack_require__(8878);
+      const _routercontextsharedruntime = __webpack_require__(5111);
+      const _useintersection = __webpack_require__(6873);
+      const _getdomainlocale = __webpack_require__(4554);
+      const _addbasepath = __webpack_require__(9567);
+      const _usemergedref = __webpack_require__(4308);
       const prefetched = new Set();
       function prefetch(router, href, as, options) {
         if (false) {
@@ -351,7 +368,167 @@
       /***/
     },
 
-    /***/ 3981: /***/ (module, exports, __webpack_require__) => {
+    /***/ 3072: /***/ (
+      __unused_webpack_module,
+      __webpack_exports__,
+      __webpack_require__
+    ) => {
+      "use strict";
+      __webpack_require__.r(__webpack_exports__);
+      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
+        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
+        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
+        /* harmony export */
+      });
+      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
+        __webpack_require__(1503);
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
+        __webpack_require__(6929);
+      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
+        /*#__PURE__*/ __webpack_require__.n(
+          next_link__WEBPACK_IMPORTED_MODULE_1__
+        );
+
+      function aLink(props) {
+        return /*#__PURE__*/ (0,
+        react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", {
+          children: [
+            /*#__PURE__*/ (0,
+            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("h3", {
+              children: "A Link page!",
+            }),
+            /*#__PURE__*/ (0,
+            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
+              next_link__WEBPACK_IMPORTED_MODULE_1___default(),
+              {
+                href: "/",
+                children: "Go to /",
+              }
+            ),
+          ],
+        });
+      }
+      var __N_SSP = true;
+      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = aLink;
+
+      /***/
+    },
+
+    /***/ 4308: /***/ (module, exports, __webpack_require__) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "useMergedRef", {
+        enumerable: true,
+        get: function () {
+          return useMergedRef;
+        },
+      });
+      const _react = __webpack_require__(2223);
+      function useMergedRef(refA, refB) {
+        const cleanupA = (0, _react.useRef)(null);
+        const cleanupB = (0, _react.useRef)(null);
+        // NOTE: In theory, we could skip the wrapping if only one of the refs is non-null.
+        // (this happens often if the user doesn't pass a ref to Link/Form/Image)
+        // But this can cause us to leak a cleanup-ref into user code (previously via `<Link legacyBehavior>`),
+        // and the user might pass that ref into ref-merging library that doesn't support cleanup refs
+        // (because it hasn't been updated for React 19)
+        // which can then cause things to blow up, because a cleanup-returning ref gets called with `null`.
+        // So in practice, it's safer to be defensive and always wrap the ref, even on React 19.
+        return (0, _react.useCallback)(
+          (current) => {
+            if (current === null) {
+              const cleanupFnA = cleanupA.current;
+              if (cleanupFnA) {
+                cleanupA.current = null;
+                cleanupFnA();
+              }
+              const cleanupFnB = cleanupB.current;
+              if (cleanupFnB) {
+                cleanupB.current = null;
+                cleanupFnB();
+              }
+            } else {
+              if (refA) {
+                cleanupA.current = applyRef(refA, current);
+              }
+              if (refB) {
+                cleanupB.current = applyRef(refB, current);
+              }
+            }
+          },
+          [refA, refB]
+        );
+      }
+      function applyRef(refA, current) {
+        if (typeof refA === "function") {
+          const cleanup = refA(current);
+          if (typeof cleanup === "function") {
+            return cleanup;
+          } else {
+            return () => refA(null);
+          }
+        } else {
+          refA.current = current;
+          return () => {
+            refA.current = null;
+          };
+        }
+      }
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
+        });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=use-merged-ref.js.map
+
+      /***/
+    },
+
+    /***/ 4554: /***/ (module, exports, __webpack_require__) => {
+      "use strict";
+
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "getDomainLocale", {
+        enumerable: true,
+        get: function () {
+          return getDomainLocale;
+        },
+      });
+      const _normalizetrailingslash = __webpack_require__(7740);
+      const basePath =
+        /* unused pure expression or super */ null && (false || "");
+      function getDomainLocale(path, locale, locales, domainLocales) {
+        if (false) {
+        } else {
+          return false;
+        }
+      }
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
+        });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=get-domain-locale.js.map
+
+      /***/
+    },
+
+    /***/ 6873: /***/ (module, exports, __webpack_require__) => {
       "use strict";
 
       Object.defineProperty(exports, "__esModule", {
@@ -364,7 +541,7 @@
         },
       });
       const _react = __webpack_require__(2223);
-      const _requestidlecallback = __webpack_require__(1472);
+      const _requestidlecallback = __webpack_require__(6892);
       const hasIntersectionObserver =
         typeof IntersectionObserver === "function";
       const observers = new Map();
@@ -476,189 +653,12 @@
       /***/
     },
 
-    /***/ 4206: /***/ (module, exports, __webpack_require__) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "getDomainLocale", {
-        enumerable: true,
-        get: function () {
-          return getDomainLocale;
-        },
-      });
-      const _normalizetrailingslash = __webpack_require__(6704);
-      const basePath =
-        /* unused pure expression or super */ null && (false || "");
-      function getDomainLocale(path, locale, locales, domainLocales) {
-        if (false) {
-        } else {
-          return false;
-        }
-      }
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=get-domain-locale.js.map
-
-      /***/
-    },
-
-    /***/ 6691: /***/ (
+    /***/ 6929: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(3262);
-
-      /***/
-    },
-
-    /***/ 6771: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/link",
-        function () {
-          return __webpack_require__(8178);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 6848: /***/ (module, exports, __webpack_require__) => {
-      "use strict";
-
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "useMergedRef", {
-        enumerable: true,
-        get: function () {
-          return useMergedRef;
-        },
-      });
-      const _react = __webpack_require__(2223);
-      function useMergedRef(refA, refB) {
-        const cleanupA = (0, _react.useRef)(null);
-        const cleanupB = (0, _react.useRef)(null);
-        // NOTE: In theory, we could skip the wrapping if only one of the refs is non-null.
-        // (this happens often if the user doesn't pass a ref to Link/Form/Image)
-        // But this can cause us to leak a cleanup-ref into user code (previously via `<Link legacyBehavior>`),
-        // and the user might pass that ref into ref-merging library that doesn't support cleanup refs
-        // (because it hasn't been updated for React 19)
-        // which can then cause things to blow up, because a cleanup-returning ref gets called with `null`.
-        // So in practice, it's safer to be defensive and always wrap the ref, even on React 19.
-        return (0, _react.useCallback)(
-          (current) => {
-            if (current === null) {
-              const cleanupFnA = cleanupA.current;
-              if (cleanupFnA) {
-                cleanupA.current = null;
-                cleanupFnA();
-              }
-              const cleanupFnB = cleanupB.current;
-              if (cleanupFnB) {
-                cleanupB.current = null;
-                cleanupFnB();
-              }
-            } else {
-              if (refA) {
-                cleanupA.current = applyRef(refA, current);
-              }
-              if (refB) {
-                cleanupB.current = applyRef(refB, current);
-              }
-            }
-          },
-          [refA, refB]
-        );
-      }
-      function applyRef(refA, current) {
-        if (typeof refA === "function") {
-          const cleanup = refA(current);
-          if (typeof cleanup === "function") {
-            return cleanup;
-          } else {
-            return () => refA(null);
-          }
-        } else {
-          refA.current = current;
-          return () => {
-            refA.current = null;
-          };
-        }
-      }
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=use-merged-ref.js.map
-
-      /***/
-    },
-
-    /***/ 8178: /***/ (
-      __unused_webpack_module,
-      __webpack_exports__,
-      __webpack_require__
-    ) => {
-      "use strict";
-      __webpack_require__.r(__webpack_exports__);
-      /* harmony export */ __webpack_require__.d(__webpack_exports__, {
-        /* harmony export */ __N_SSP: () => /* binding */ __N_SSP,
-        /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__,
-        /* harmony export */
-      });
-      /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
-        __webpack_require__(1503);
-      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(6691);
-      /* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
-        /*#__PURE__*/ __webpack_require__.n(
-          next_link__WEBPACK_IMPORTED_MODULE_1__
-        );
-
-      function aLink(props) {
-        return /*#__PURE__*/ (0,
-        react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", {
-          children: [
-            /*#__PURE__*/ (0,
-            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("h3", {
-              children: "A Link page!",
-            }),
-            /*#__PURE__*/ (0,
-            react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(
-              next_link__WEBPACK_IMPORTED_MODULE_1___default(),
-              {
-                href: "/",
-                children: "Go to /",
-              }
-            ),
-          ],
-        });
-      }
-      var __N_SSP = true;
-      /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = aLink;
+      module.exports = __webpack_require__(3066);
 
       /***/
     },
@@ -668,7 +668,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(6771)
+      __webpack_exec__(2025)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for routerDirect-HASH.js
@@ -1,7 +1,24 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [188],
   {
-    /***/ 286: /***/ (
+    /***/ 417: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/routerDirect",
+        function () {
+          return __webpack_require__(504);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 504: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -16,7 +33,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(1503);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(7798);
+        __webpack_require__(1840);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -36,29 +53,12 @@
       /***/
     },
 
-    /***/ 4283: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/routerDirect",
-        function () {
-          return __webpack_require__(286);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
-
-    /***/ 7798: /***/ (
+    /***/ 1840: /***/ (
       module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(9587);
+      module.exports = __webpack_require__(1903);
 
       /***/
     },
@@ -68,7 +68,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(4283)
+      __webpack_exec__(417)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for script-HASH.js
@@ -1,7 +1,34 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [1209],
   {
-    /***/ 661: /***/ (
+    /***/ 2398: /***/ (
+      module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      module.exports = __webpack_require__(2397);
+
+      /***/
+    },
+
+    /***/ 4305: /***/ (
+      __unused_webpack_module,
+      __unused_webpack_exports,
+      __webpack_require__
+    ) => {
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/script",
+        function () {
+          return __webpack_require__(8543);
+        },
+      ]);
+      if (false) {
+      }
+
+      /***/
+    },
+
+    /***/ 8543: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -16,7 +43,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(1503);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(5964);
+        __webpack_require__(2398);
       /* harmony import */ var next_script__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_script__WEBPACK_IMPORTED_MODULE_1__
@@ -48,40 +75,13 @@
 
       /***/
     },
-
-    /***/ 5964: /***/ (
-      module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      module.exports = __webpack_require__(297);
-
-      /***/
-    },
-
-    /***/ 8803: /***/ (
-      __unused_webpack_module,
-      __unused_webpack_exports,
-      __webpack_require__
-    ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/script",
-        function () {
-          return __webpack_require__(661);
-        },
-      ]);
-      if (false) {
-      }
-
-      /***/
-    },
   },
   /******/ (__webpack_require__) => {
     // webpackRuntimeModules
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(8803)
+      __webpack_exec__(4305)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for withRouter-HASH.js
@@ -1,24 +1,17 @@
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
   [3263],
   {
-    /***/ 3163: /***/ (
-      __unused_webpack_module,
+    /***/ 1840: /***/ (
+      module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      (window.__NEXT_P = window.__NEXT_P || []).push([
-        "/withRouter",
-        function () {
-          return __webpack_require__(3295);
-        },
-      ]);
-      if (false) {
-      }
+      module.exports = __webpack_require__(1903);
 
       /***/
     },
 
-    /***/ 3295: /***/ (
+    /***/ 2037: /***/ (
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
@@ -33,7 +26,7 @@
       /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
         __webpack_require__(1503);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1__ =
-        __webpack_require__(7798);
+        __webpack_require__(1840);
       /* harmony import */ var next_router__WEBPACK_IMPORTED_MODULE_1___default =
         /*#__PURE__*/ __webpack_require__.n(
           next_router__WEBPACK_IMPORTED_MODULE_1__
@@ -52,12 +45,19 @@
       /***/
     },
 
-    /***/ 7798: /***/ (
-      module,
+    /***/ 4041: /***/ (
+      __unused_webpack_module,
       __unused_webpack_exports,
       __webpack_require__
     ) => {
-      module.exports = __webpack_require__(9587);
+      (window.__NEXT_P = window.__NEXT_P || []).push([
+        "/withRouter",
+        function () {
+          return __webpack_require__(2037);
+        },
+      ]);
+      if (false) {
+      }
 
       /***/
     },
@@ -67,7 +67,7 @@
     /******/ var __webpack_exec__ = (moduleId) =>
       __webpack_require__((__webpack_require__.s = moduleId));
     /******/ __webpack_require__.O(0, [636, 6593, 8792], () =>
-      __webpack_exec__(3163)
+      __webpack_exec__(4041)
     );
     /******/ var __webpack_exports__ = __webpack_require__.O();
     /******/ _N_E = __webpack_exports__;
Diff for 7322-HASH.js

Diff too large to display

Diff for 9225-HASH.js
@@ -1,32 +1,81 @@
 "use strict";
 (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
-  [9225],
+  [8439],
   {
-    /***/ 2: /***/ (__unused_webpack_module, exports, __webpack_require__) => {
+    /***/ 405: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
-      Object.defineProperty(exports, "ImageConfigContext", {
+      Object.defineProperty(exports, "default", {
         enumerable: true,
         get: function () {
-          return ImageConfigContext;
+          return SideEffect;
         },
       });
-      const _interop_require_default = __webpack_require__(9010);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(8879)
-      );
-      const _imageconfig = __webpack_require__(1686);
-      const ImageConfigContext = _react.default.createContext(
-        _imageconfig.imageConfigDefault
-      );
-      if (false) {
-      } //# sourceMappingURL=image-config-context.shared-runtime.js.map
+      const _react = __webpack_require__(1774);
+      const isServer = "object" === "undefined";
+      const useClientOnlyLayoutEffect = isServer
+        ? () => {}
+        : _react.useLayoutEffect;
+      const useClientOnlyEffect = isServer ? () => {} : _react.useEffect;
+      function SideEffect(props) {
+        const { headManager, reduceComponentsToState } = props;
+        function emitChange() {
+          if (headManager && headManager.mountedInstances) {
+            const headElements = _react.Children.toArray(
+              Array.from(headManager.mountedInstances).filter(Boolean)
+            );
+            headManager.updateHead(reduceComponentsToState(headElements));
+          }
+        }
+        if (isServer) {
+          headManager?.mountedInstances?.add(props.children);
+          emitChange();
+        }
+        useClientOnlyLayoutEffect(() => {
+          headManager?.mountedInstances?.add(props.children);
+          return () => {
+            headManager?.mountedInstances?.delete(props.children);
+          };
+        });
+        // We need to call `updateHead` method whenever the `SideEffect` is trigger in all
+        // life-cycles: mount, update, unmount. However, if there are multiple `SideEffect`s
+        // being rendered, we only trigger the method from the last one.
+        // This is ensured by keeping the last unflushed `updateHead` in the `_pendingUpdate`
+        // singleton in the layout effect pass, and actually trigger it in the effect pass.
+        useClientOnlyLayoutEffect(() => {
+          if (headManager) {
+            headManager._pendingUpdate = emitChange;
+          }
+          return () => {
+            if (headManager) {
+              headManager._pendingUpdate = emitChange;
+            }
+          };
+        });
+        useClientOnlyEffect(() => {
+          if (headManager && headManager._pendingUpdate) {
+            headManager._pendingUpdate();
+            headManager._pendingUpdate = null;
+          }
+          return () => {
+            if (headManager && headManager._pendingUpdate) {
+              headManager._pendingUpdate();
+              headManager._pendingUpdate = null;
+            }
+          };
+        });
+        return null;
+      } //# sourceMappingURL=side-effect.js.map
 
       /***/
     },
 
-    /***/ 1169: /***/ (
+    /***/ 1155: /***/ (
       __unused_webpack_module,
       exports,
       __webpack_require__
@@ -40,9 +89,9 @@
           return getImgProps;
         },
       });
-      const _warnonce = __webpack_require__(4352);
-      const _imageblursvg = __webpack_require__(2314);
-      const _imageconfig = __webpack_require__(1686);
+      const _warnonce = __webpack_require__(5358);
+      const _imageblursvg = __webpack_require__(6924);
+      const _imageconfig = __webpack_require__(9712);
       const VALID_LOADING_VALUES =
         /* unused pure expression or super */ null && [
           "lazy",
@@ -473,241 +522,40 @@
       /***/
     },
 
-    /***/ 1666: /***/ (module, exports, __webpack_require__) => {
-      /* __next_internal_client_entry_do_not_use__  cjs */
+    /***/ 1417: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
-      0 && 0;
-      function _export(target, all) {
-        for (var name in all)
-          Object.defineProperty(target, name, {
-            enumerable: true,
-            get: all[name],
-          });
-      }
-      _export(exports, {
-        default: function () {
+      Object.defineProperty(exports, "default", {
+        enumerable: true,
+        get: function () {
           return _default;
         },
-        defaultHead: function () {
-          return defaultHead;
-        },
       });
-      const _interop_require_default = __webpack_require__(9010);
-      const _interop_require_wildcard = __webpack_require__(2275);
-      const _jsxruntime = __webpack_require__(1024);
-      const _react = /*#__PURE__*/ _interop_require_wildcard._(
-        __webpack_require__(8879)
-      );
-      const _sideeffect = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(2543)
-      );
-      const _headmanagercontextsharedruntime = __webpack_require__(5428);
-      const _warnonce = __webpack_require__(4352);
-      function defaultHead() {
-        const head = [
-          /*#__PURE__*/ (0, _jsxruntime.jsx)(
-            "meta",
-            {
-              charSet: "utf-8",
-            },
-            "charset"
-          ),
-          /*#__PURE__*/ (0, _jsxruntime.jsx)(
-            "meta",
-            {
-              name: "viewport",
-              content: "width=device-width",
-            },
-            "viewport"
-          ),
-        ];
-        return head;
-      }
-      function onlyReactElement(list, child) {
-        // React children can be "string" or "number" in this case we ignore them for backwards compat
-        if (typeof child === "string" || typeof child === "number") {
-          return list;
-        }
-        // Adds support for React.Fragment
-        if (child.type === _react.default.Fragment) {
-          return list.concat(
-            _react.default.Children.toArray(child.props.children).reduce(
-              (fragmentList, fragmentChild) => {
-                if (
-                  typeof fragmentChild === "string" ||
-                  typeof fragmentChild === "number"
-                ) {
-                  return fragmentList;
-                }
-                return fragmentList.concat(fragmentChild);
-              },
-              []
-            )
-          );
+      const _findclosestquality = __webpack_require__(1639);
+      function defaultLoader({ config, src, width, quality }) {
+        if (false) {
         }
-        return list.concat(child);
-      }
-      const METATYPES = ["name", "httpEquiv", "charSet", "itemProp"];
-      /*
- returns a function for filtering head child elements
- which shouldn't be duplicated, like <title/>
- Also adds support for deduplicated `key` properties
-*/ function unique() {
-        const keys = new Set();
-        const tags = new Set();
-        const metaTypes = new Set();
-        const metaCategories = {};
-        return (h) => {
-          let isUnique = true;
-          let hasKey = false;
-          if (h.key && typeof h.key !== "number" && h.key.indexOf("$") > 0) {
-            hasKey = true;
-            const key = h.key.slice(h.key.indexOf("$") + 1);
-            if (keys.has(key)) {
-              isUnique = false;
-            } else {
-              keys.add(key);
-            }
-          }
-          // eslint-disable-next-line default-case
-          switch (h.type) {
-            case "title":
-            case "base":
-              if (tags.has(h.type)) {
-                isUnique = false;
-              } else {
-                tags.add(h.type);
-              }
-              break;
-            case "meta":
-              for (let i = 0, len = METATYPES.length; i < len; i++) {
-                const metatype = METATYPES[i];
-                if (!h.props.hasOwnProperty(metatype)) continue;
-                if (metatype === "charSet") {
-                  if (metaTypes.has(metatype)) {
-                    isUnique = false;
-                  } else {
-                    metaTypes.add(metatype);
-                  }
-                } else {
-                  const category = h.props[metatype];
-                  const categories = metaCategories[metatype] || new Set();
-                  if (
-                    (metatype !== "name" || !hasKey) &&
-                    categories.has(category)
-                  ) {
-                    isUnique = false;
-                  } else {
-                    categories.add(category);
-                    metaCategories[metatype] = categories;
-                  }
-                }
-              }
-              break;
-          }
-          return isUnique;
-        };
-      }
-      /**
-       *
-       * @param headChildrenElements List of children of <Head>
-       */ function reduceComponents(headChildrenElements) {
-        return headChildrenElements
-          .reduce(onlyReactElement, [])
-          .reverse()
-          .concat(defaultHead().reverse())
-          .filter(unique())
-          .reverse()
-          .map((c, i) => {
-            const key = c.key || i;
-            if (false) {
-            }
-            return /*#__PURE__*/ _react.default.cloneElement(c, {
-              key,
-            });
-          });
-      }
-      /**
-       * This component injects elements to `<head>` of your page.
-       * To avoid duplicated `tags` in `<head>` you can use the `key` property, which will make sure every tag is only rendered once.
-       */ function Head({ children }) {
-        const headManager = (0, _react.useContext)(
-          _headmanagercontextsharedruntime.HeadManagerContext
-        );
-        return /*#__PURE__*/ (0, _jsxruntime.jsx)(_sideeffect.default, {
-          reduceComponentsToState: reduceComponents,
-          headManager: headManager,
-          children: children,
-        });
-      }
-      const _default = Head;
-      if (
-        (typeof exports.default === "function" ||
-          (typeof exports.default === "object" && exports.default !== null)) &&
-        typeof exports.default.__esModule === "undefined"
-      ) {
-        Object.defineProperty(exports.default, "__esModule", {
-          value: true,
-        });
-        Object.assign(exports.default, exports);
-        module.exports = exports.default;
-      } //# sourceMappingURL=head.js.map
-
-      /***/
-    },
-
-    /***/ 1686: /***/ (__unused_webpack_module, exports) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      0 && 0;
-      function _export(target, all) {
-        for (var name in all)
-          Object.defineProperty(target, name, {
-            enumerable: true,
-            get: all[name],
-          });
+        const q = (0, _findclosestquality.findClosestQuality)(quality, config);
+        return `${config.path}?url=${encodeURIComponent(
+          src
+        )}&w=${width}&q=${q}${
+          src.startsWith("/_next/static/media/") && false ? 0 : ""
+        }`;
       }
-      _export(exports, {
-        VALID_LOADERS: function () {
-          return VALID_LOADERS;
-        },
-        imageConfigDefault: function () {
-          return imageConfigDefault;
-        },
-      });
-      const VALID_LOADERS = [
-        "default",
-        "imgix",
-        "cloudinary",
-        "akamai",
-        "custom",
-      ];
-      const imageConfigDefault = {
-        deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
-        imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
-        path: "/_next/image",
-        loader: "default",
-        loaderFile: "",
-        domains: [],
-        disableStaticImages: false,
-        minimumCacheTTL: 14400,
-        formats: ["image/webp"],
-        dangerouslyAllowSVG: false,
-        contentSecurityPolicy: `script-src 'none'; frame-src 'none'; sandbox;`,
-        contentDispositionType: "attachment",
-        localPatterns: undefined,
-        remotePatterns: [],
-        qualities: [75],
-        unoptimized: false,
-      }; //# sourceMappingURL=image-config.js.map
+      // We use this to determine if the import is the default loader
+      // or a custom loader defined by the user in next.config.js
+      defaultLoader.__next_img_default = true;
+      const _default = defaultLoader; //# sourceMappingURL=image-loader.js.map
 
       /***/
     },
 
-    /***/ 2285: /***/ (__unused_webpack_module, exports) => {
+    /***/ 1639: /***/ (__unused_webpack_module, exports) => {
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
@@ -731,7 +579,35 @@
       /***/
     },
 
-    /***/ 2314: /***/ (__unused_webpack_module, exports) => {
+    /***/ 2896: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "ImageConfigContext", {
+        enumerable: true,
+        get: function () {
+          return ImageConfigContext;
+        },
+      });
+      const _interop_require_default = __webpack_require__(2570);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(1774)
+      );
+      const _imageconfig = __webpack_require__(9712);
+      const ImageConfigContext = _react.default.createContext(
+        _imageconfig.imageConfigDefault
+      );
+      if (false) {
+      } //# sourceMappingURL=image-config-context.shared-runtime.js.map
+
+      /***/
+    },
+
+    /***/ 6924: /***/ (__unused_webpack_module, exports) => {
       /**
        * A shared function, used on both client and server, to generate a SVG blur placeholder.
        */
@@ -770,113 +646,7 @@
       /***/
     },
 
-    /***/ 2543: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "default", {
-        enumerable: true,
-        get: function () {
-          return SideEffect;
-        },
-      });
-      const _react = __webpack_require__(8879);
-      const isServer = "object" === "undefined";
-      const useClientOnlyLayoutEffect = isServer
-        ? () => {}
-        : _react.useLayoutEffect;
-      const useClientOnlyEffect = isServer ? () => {} : _react.useEffect;
-      function SideEffect(props) {
-        const { headManager, reduceComponentsToState } = props;
-        function emitChange() {
-          if (headManager && headManager.mountedInstances) {
-            const headElements = _react.Children.toArray(
-              Array.from(headManager.mountedInstances).filter(Boolean)
-            );
-            headManager.updateHead(reduceComponentsToState(headElements));
-          }
-        }
-        if (isServer) {
-          headManager?.mountedInstances?.add(props.children);
-          emitChange();
-        }
-        useClientOnlyLayoutEffect(() => {
-          headManager?.mountedInstances?.add(props.children);
-          return () => {
-            headManager?.mountedInstances?.delete(props.children);
-          };
-        });
-        // We need to call `updateHead` method whenever the `SideEffect` is trigger in all
-        // life-cycles: mount, update, unmount. However, if there are multiple `SideEffect`s
-        // being rendered, we only trigger the method from the last one.
-        // This is ensured by keeping the last unflushed `updateHead` in the `_pendingUpdate`
-        // singleton in the layout effect pass, and actually trigger it in the effect pass.
-        useClientOnlyLayoutEffect(() => {
-          if (headManager) {
-            headManager._pendingUpdate = emitChange;
-          }
-          return () => {
-            if (headManager) {
-              headManager._pendingUpdate = emitChange;
-            }
-          };
-        });
-        useClientOnlyEffect(() => {
-          if (headManager && headManager._pendingUpdate) {
-            headManager._pendingUpdate();
-            headManager._pendingUpdate = null;
-          }
-          return () => {
-            if (headManager && headManager._pendingUpdate) {
-              headManager._pendingUpdate();
-              headManager._pendingUpdate = null;
-            }
-          };
-        });
-        return null;
-      } //# sourceMappingURL=side-effect.js.map
-
-      /***/
-    },
-
-    /***/ 8035: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "default", {
-        enumerable: true,
-        get: function () {
-          return _default;
-        },
-      });
-      const _findclosestquality = __webpack_require__(2285);
-      function defaultLoader({ config, src, width, quality }) {
-        if (false) {
-        }
-        const q = (0, _findclosestquality.findClosestQuality)(quality, config);
-        return `${config.path}?url=${encodeURIComponent(
-          src
-        )}&w=${width}&q=${q}${
-          src.startsWith("/_next/static/media/") && false ? 0 : ""
-        }`;
-      }
-      // We use this to determine if the import is the default loader
-      // or a custom loader defined by the user in next.config.js
-      defaultLoader.__next_img_default = true;
-      const _default = defaultLoader; //# sourceMappingURL=image-loader.js.map
-
-      /***/
-    },
-
-    /***/ 8848: /***/ (module, exports, __webpack_require__) => {
+    /***/ 7614: /***/ (module, exports, __webpack_require__) => {
       Object.defineProperty(exports, "__esModule", {
         value: true,
       });
@@ -886,7 +656,7 @@
           return useMergedRef;
         },
       });
-      const _react = __webpack_require__(8879);
+      const _react = __webpack_require__(1774);
       function useMergedRef(refA, refB) {
         const cleanupA = (0, _react.useRef)(null);
         const cleanupB = (0, _react.useRef)(null);
@@ -952,32 +722,7 @@
       /***/
     },
 
-    /***/ 9059: /***/ (
-      __unused_webpack_module,
-      exports,
-      __webpack_require__
-    ) => {
-      Object.defineProperty(exports, "__esModule", {
-        value: true,
-      });
-      Object.defineProperty(exports, "RouterContext", {
-        enumerable: true,
-        get: function () {
-          return RouterContext;
-        },
-      });
-      const _interop_require_default = __webpack_require__(9010);
-      const _react = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(8879)
-      );
-      const RouterContext = _react.default.createContext(null);
-      if (false) {
-      } //# sourceMappingURL=router-context.shared-runtime.js.map
-
-      /***/
-    },
-
-    /***/ 9225: /***/ (module, exports, __webpack_require__) => {
+    /***/ 8439: /***/ (module, exports, __webpack_require__) => {
       /* __next_internal_client_entry_do_not_use__  cjs */
       Object.defineProperty(exports, "__esModule", {
         value: true,
@@ -988,27 +733,27 @@
           return Image;
         },
       });
-      const _interop_require_default = __webpack_require__(9010);
-      const _interop_require_wildcard = __webpack_require__(2275);
-      const _jsxruntime = __webpack_require__(1024);
+      const _interop_require_default = __webpack_require__(2570);
+      const _interop_require_wildcard = __webpack_require__(5643);
+      const _jsxruntime = __webpack_require__(2014);
       const _react = /*#__PURE__*/ _interop_require_wildcard._(
-        __webpack_require__(8879)
+        __webpack_require__(1774)
       );
       const _reactdom = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(3869)
+        __webpack_require__(7499)
       );
       const _head = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(1666)
+        __webpack_require__(9452)
       );
-      const _getimgprops = __webpack_require__(1169);
-      const _imageconfig = __webpack_require__(1686);
-      const _imageconfigcontextsharedruntime = __webpack_require__(2);
-      const _warnonce = __webpack_require__(4352);
-      const _routercontextsharedruntime = __webpack_require__(9059);
+      const _getimgprops = __webpack_require__(1155);
+      const _imageconfig = __webpack_require__(9712);
+      const _imageconfigcontextsharedruntime = __webpack_require__(2896);
+      const _warnonce = __webpack_require__(5358);
+      const _routercontextsharedruntime = __webpack_require__(9813);
       const _imageloader = /*#__PURE__*/ _interop_require_default._(
-        __webpack_require__(8035)
+        __webpack_require__(1417)
       );
-      const _usemergedref = __webpack_require__(8848);
+      const _usemergedref = __webpack_require__(7614);
       // This is replaced by webpack define plugin
       const configEnv = {
         deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
@@ -1329,5 +1074,264 @@
 
       /***/
     },
+
+    /***/ 9452: /***/ (module, exports, __webpack_require__) => {
+      /* __next_internal_client_entry_do_not_use__  cjs */
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      0 && 0;
+      function _export(target, all) {
+        for (var name in all)
+          Object.defineProperty(target, name, {
+            enumerable: true,
+            get: all[name],
+          });
+      }
+      _export(exports, {
+        default: function () {
+          return _default;
+        },
+        defaultHead: function () {
+          return defaultHead;
+        },
+      });
+      const _interop_require_default = __webpack_require__(2570);
+      const _interop_require_wildcard = __webpack_require__(5643);
+      const _jsxruntime = __webpack_require__(2014);
+      const _react = /*#__PURE__*/ _interop_require_wildcard._(
+        __webpack_require__(1774)
+      );
+      const _sideeffect = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(405)
+      );
+      const _headmanagercontextsharedruntime = __webpack_require__(5326);
+      const _warnonce = __webpack_require__(5358);
+      function defaultHead() {
+        const head = [
+          /*#__PURE__*/ (0, _jsxruntime.jsx)(
+            "meta",
+            {
+              charSet: "utf-8",
+            },
+            "charset"
+          ),
+          /*#__PURE__*/ (0, _jsxruntime.jsx)(
+            "meta",
+            {
+              name: "viewport",
+              content: "width=device-width",
+            },
+            "viewport"
+          ),
+        ];
+        return head;
+      }
+      function onlyReactElement(list, child) {
+        // React children can be "string" or "number" in this case we ignore them for backwards compat
+        if (typeof child === "string" || typeof child === "number") {
+          return list;
+        }
+        // Adds support for React.Fragment
+        if (child.type === _react.default.Fragment) {
+          return list.concat(
+            _react.default.Children.toArray(child.props.children).reduce(
+              (fragmentList, fragmentChild) => {
+                if (
+                  typeof fragmentChild === "string" ||
+                  typeof fragmentChild === "number"
+                ) {
+                  return fragmentList;
+                }
+                return fragmentList.concat(fragmentChild);
+              },
+              []
+            )
+          );
+        }
+        return list.concat(child);
+      }
+      const METATYPES = ["name", "httpEquiv", "charSet", "itemProp"];
+      /*
+ returns a function for filtering head child elements
+ which shouldn't be duplicated, like <title/>
+ Also adds support for deduplicated `key` properties
+*/ function unique() {
+        const keys = new Set();
+        const tags = new Set();
+        const metaTypes = new Set();
+        const metaCategories = {};
+        return (h) => {
+          let isUnique = true;
+          let hasKey = false;
+          if (h.key && typeof h.key !== "number" && h.key.indexOf("$") > 0) {
+            hasKey = true;
+            const key = h.key.slice(h.key.indexOf("$") + 1);
+            if (keys.has(key)) {
+              isUnique = false;
+            } else {
+              keys.add(key);
+            }
+          }
+          // eslint-disable-next-line default-case
+          switch (h.type) {
+            case "title":
+            case "base":
+              if (tags.has(h.type)) {
+                isUnique = false;
+              } else {
+                tags.add(h.type);
+              }
+              break;
+            case "meta":
+              for (let i = 0, len = METATYPES.length; i < len; i++) {
+                const metatype = METATYPES[i];
+                if (!h.props.hasOwnProperty(metatype)) continue;
+                if (metatype === "charSet") {
+                  if (metaTypes.has(metatype)) {
+                    isUnique = false;
+                  } else {
+                    metaTypes.add(metatype);
+                  }
+                } else {
+                  const category = h.props[metatype];
+                  const categories = metaCategories[metatype] || new Set();
+                  if (
+                    (metatype !== "name" || !hasKey) &&
+                    categories.has(category)
+                  ) {
+                    isUnique = false;
+                  } else {
+                    categories.add(category);
+                    metaCategories[metatype] = categories;
+                  }
+                }
+              }
+              break;
+          }
+          return isUnique;
+        };
+      }
+      /**
+       *
+       * @param headChildrenElements List of children of <Head>
+       */ function reduceComponents(headChildrenElements) {
+        return headChildrenElements
+          .reduce(onlyReactElement, [])
+          .reverse()
+          .concat(defaultHead().reverse())
+          .filter(unique())
+          .reverse()
+          .map((c, i) => {
+            const key = c.key || i;
+            if (false) {
+            }
+            return /*#__PURE__*/ _react.default.cloneElement(c, {
+              key,
+            });
+          });
+      }
+      /**
+       * This component injects elements to `<head>` of your page.
+       * To avoid duplicated `tags` in `<head>` you can use the `key` property, which will make sure every tag is only rendered once.
+       */ function Head({ children }) {
+        const headManager = (0, _react.useContext)(
+          _headmanagercontextsharedruntime.HeadManagerContext
+        );
+        return /*#__PURE__*/ (0, _jsxruntime.jsx)(_sideeffect.default, {
+          reduceComponentsToState: reduceComponents,
+          headManager: headManager,
+          children: children,
+        });
+      }
+      const _default = Head;
+      if (
+        (typeof exports.default === "function" ||
+          (typeof exports.default === "object" && exports.default !== null)) &&
+        typeof exports.default.__esModule === "undefined"
+      ) {
+        Object.defineProperty(exports.default, "__esModule", {
+          value: true,
+        });
+        Object.assign(exports.default, exports);
+        module.exports = exports.default;
+      } //# sourceMappingURL=head.js.map
+
+      /***/
+    },
+
+    /***/ 9712: /***/ (__unused_webpack_module, exports) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      0 && 0;
+      function _export(target, all) {
+        for (var name in all)
+          Object.defineProperty(target, name, {
+            enumerable: true,
+            get: all[name],
+          });
+      }
+      _export(exports, {
+        VALID_LOADERS: function () {
+          return VALID_LOADERS;
+        },
+        imageConfigDefault: function () {
+          return imageConfigDefault;
+        },
+      });
+      const VALID_LOADERS = [
+        "default",
+        "imgix",
+        "cloudinary",
+        "akamai",
+        "custom",
+      ];
+      const imageConfigDefault = {
+        deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
+        imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
+        path: "/_next/image",
+        loader: "default",
+        loaderFile: "",
+        domains: [],
+        disableStaticImages: false,
+        minimumCacheTTL: 14400,
+        formats: ["image/webp"],
+        dangerouslyAllowSVG: false,
+        contentSecurityPolicy: `script-src 'none'; frame-src 'none'; sandbox;`,
+        contentDispositionType: "attachment",
+        localPatterns: undefined,
+        remotePatterns: [],
+        qualities: [75],
+        unoptimized: false,
+      }; //# sourceMappingURL=image-config.js.map
+
+      /***/
+    },
+
+    /***/ 9813: /***/ (
+      __unused_webpack_module,
+      exports,
+      __webpack_require__
+    ) => {
+      Object.defineProperty(exports, "__esModule", {
+        value: true,
+      });
+      Object.defineProperty(exports, "RouterContext", {
+        enumerable: true,
+        get: function () {
+          return RouterContext;
+        },
+      });
+      const _interop_require_default = __webpack_require__(2570);
+      const _react = /*#__PURE__*/ _interop_require_default._(
+        __webpack_require__(1774)
+      );
+      const RouterContext = _react.default.createContext(null);
+      if (false) {
+      } //# sourceMappingURL=router-context.shared-runtime.js.map
+
+      /***/
+    },
   },
 ]);
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-exp..time.prod.js

Diff too large to display

Diff for app-page-tur..ntime.dev.js

Diff too large to display

Diff for app-page-tur..time.prod.js

Diff too large to display

Diff for app-page-tur..ntime.dev.js

Diff too large to display

Diff for app-page-tur..time.prod.js

Diff too large to display

Diff for app-page.runtime.dev.js

Diff too large to display

Diff for app-page.runtime.prod.js

Diff too large to display

Commit: cfc26b0

@gaojude gaojude force-pushed the jude/devtools-api-and-mcp branch from eb4ef34 to 0f14add Compare October 5, 2025 08:00
return
}

const responses = await createBrowserRequest<PageMetadata>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API handler uses the wrong TypeScript type for page metadata responses. It uses PageMetadata (which has a segments field) when it should use SegmentTrieData (which has a segmentTrie field).

View Details
📝 Patch Details
diff --git a/packages/next/src/server/dev/devtools-api/page-metadata.ts b/packages/next/src/server/dev/devtools-api/page-metadata.ts
index ebd1641e00..28e4fdad30 100644
--- a/packages/next/src/server/dev/devtools-api/page-metadata.ts
+++ b/packages/next/src/server/dev/devtools-api/page-metadata.ts
@@ -1,6 +1,6 @@
 import type { ServerResponse } from 'http'
 import type { HmrMessageSentToBrowser } from '../hot-reloader-types'
-import type { PageMetadata } from '../../../shared/lib/devtools-api-types'
+import type { SegmentTrieData } from '../../../shared/lib/devtools-api-types'
 import { HMR_MESSAGE_SENT_TO_BROWSER } from '../hot-reloader-types'
 import { createBrowserRequest } from '../../lib/devtools-api-utils/tools/utils/browser-communication'
 
@@ -23,14 +23,14 @@ export async function handlePageMetadataRequest(
     return
   }
 
-  const responses = await createBrowserRequest<PageMetadata>(
+  const responses = await createBrowserRequest<SegmentTrieData | null>(
     HMR_MESSAGE_SENT_TO_BROWSER.REQUEST_PAGE_METADATA,
     sendHmrMessage,
     getActiveConnectionCount,
     5000
   )
 
-  const metadataByUrl = new Map<string, PageMetadata>()
+  const metadataByUrl = new Map<string, SegmentTrieData | null>()
   for (const response of responses) {
     if (response.data) {
       metadataByUrl.set(response.url, response.data)

Analysis

Type mismatch in handlePageMetadataRequest causes incorrect TypeScript types for API response

What fails: The handlePageMetadataRequest function in packages/next/src/server/dev/devtools-api/page-metadata.ts uses incorrect TypeScript type PageMetadata (with segments field) when browser clients actually send SegmentTrieData (with segmentTrie field).

How to reproduce:

  1. Start Next.js dev server with devtools API enabled
  2. Open browser dev tools and navigate to a page
  3. Call /_next/devtools-api/page-metadata endpoint
  4. Response contains segmentTrie field at runtime, but TypeScript thinks it's segments

Result: TypeScript type annotations don't match runtime data structure. The browser sends DevtoolsPageMetadataResponse with segmentTrieData: SegmentTrieData | null (containing { segmentTrie: SegmentTrieNode | null, routerType: 'app' | 'pages' }), but the API handler incorrectly types it as PageMetadata (containing { segments: PageSegment[], routerType: 'app' | 'pages' }).

Expected: API handler should use SegmentTrieData type to match the actual data structure sent by the browser. This is confirmed by:

  • Browser code in hot-reloader-app.tsx and hot-reloader-pages.ts sending segmentTrieData: SegmentTrieData
  • Server handler in hot-reloader-turbopack.ts calling handlePageMetadataResponse(requestId, segmentTrieData, url)
  • MCP server consumer in packages/next-devtools-mcp-server/src/tools/get-page-metadata.ts expecting SegmentTrieData with segmentTrie field
  • Test file test/development/devtools-api/devtools-api-get-page-metadata.test.ts asserting metadata.segmentTrie exists

Fix: Changed import from PageMetadata to SegmentTrieData and updated type annotations in createBrowserRequest and metadataByUrl Map to use correct type.

@gaojude gaojude force-pushed the jude/devtools-api-and-mcp branch from 0f14add to 265eae7 Compare October 5, 2025 08:30
Comment on lines +5 to +12
interface ServerActionResponse {
id: string
name?: string
file?: string
line?: number
column?: number
source?: string
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ServerActionResponse interface has incorrect field names that don't match what the actual API returns, causing the tool to display only the action ID without any useful information about the function name or location.

View Details
📝 Patch Details
diff --git a/packages/next-devtools-mcp-server/src/tools/get-server-action-by-id.ts b/packages/next-devtools-mcp-server/src/tools/get-server-action-by-id.ts
index 27be9ba0f4..7c45c9ab06 100644
--- a/packages/next-devtools-mcp-server/src/tools/get-server-action-by-id.ts
+++ b/packages/next-devtools-mcp-server/src/tools/get-server-action-by-id.ts
@@ -4,11 +4,12 @@ import { makeDevtoolsRequest } from '../utils/api-client'
 
 interface ServerActionResponse {
   id: string
-  name?: string
-  file?: string
-  line?: number
-  column?: number
-  source?: string
+  runtime?: 'node' | 'edge'
+  filename?: string
+  functionName?: string
+  layer?: Record<string, string>
+  workers?: Record<string, unknown>
+  error?: string
 }
 
 export function registerGetActionByIdTool(server: McpServer) {
@@ -33,27 +34,28 @@ export function registerGetActionByIdTool(server: McpServer) {
 
         lines.push(`**Server Action ID:** ${response.id}`)
 
-        if (response.name) {
-          lines.push(`**Name:** ${response.name}`)
+        if (response.error) {
+          lines.push(`**Error:** ${response.error}`)
+          return {
+            content: [
+              {
+                type: 'text',
+                text: lines.join('\n'),
+              },
+            ],
+          }
         }
 
-        if (response.file) {
-          let location = response.file
-          if (response.line !== undefined) {
-            location += `:${response.line}`
-            if (response.column !== undefined) {
-              location += `:${response.column}`
-            }
-          }
-          lines.push(`**Location:** ${location}`)
+        if (response.functionName) {
+          lines.push(`**Function Name:** ${response.functionName}`)
+        }
+
+        if (response.filename) {
+          lines.push(`**File:** ${response.filename}`)
         }
 
-        if (response.source) {
-          lines.push('')
-          lines.push('**Source:**')
-          lines.push('```typescript')
-          lines.push(response.source)
-          lines.push('```')
+        if (response.runtime) {
+          lines.push(`**Runtime:** ${response.runtime}`)
         }
 
         return {

Analysis

ServerActionResponse interface uses incorrect field names causing missing output

What fails: The get_server_action_by_id tool in packages/next-devtools-mcp-server/src/tools/get-server-action-by-id.ts defines interface fields (name, file, line, column, source) that don't match the actual API response from getServerActionInfo() in packages/next/src/server/lib/devtools-api-utils/tools/get-server-action-by-id.ts

How to reproduce: The API returns ServerActionInfo with fields: id, runtime, filename, functionName, layer, workers, error

The MCP server checks if (response.name) and if (response.file) which are always undefined, causing only the action ID to be displayed

Result: Tool output only shows **Server Action ID:** <id> and omits function name, file location, runtime, and error information

Expected: Tool should display function name (via response.functionName), file path (via response.filename), runtime (via response.runtime), and error messages (via response.error) when available, matching the actual structure returned by getServerActionInfo()

@gaojude gaojude force-pushed the jude/devtools-api-and-mcp branch 2 times, most recently from b908549 to d8798db Compare October 5, 2025 19:47
@gaojude gaojude force-pushed the jude/devtools-api-and-mcp branch from d8798db to cfc26b0 Compare October 5, 2025 20:24
*No segments found*
---"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add E2E for server action tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants