Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 49 additions & 20 deletions packages/next/src/client/components/error-boundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ export class ErrorBoundaryHandler extends React.Component<
this.state = { error: null, previousPathname: this.props.pathname }
}

static getDerivedStateFromError(error: Error) {
static getDerivedStateFromError(error: Error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The ErrorBoundaryHandler class has severe structural corruption with incomplete method definitions, duplicate declarations, and orphaned code fragments that will prevent compilation.

View Details
📝 Patch Details
diff --git a/packages/next/src/client/components/error-boundary.tsx b/packages/next/src/client/components/error-boundary.tsx
index b107d6d21e..7cfa95f71d 100644
--- a/packages/next/src/client/components/error-boundary.tsx
+++ b/packages/next/src/client/components/error-boundary.tsx
@@ -43,17 +43,17 @@ export class ErrorBoundaryHandler extends React.Component<
     this.state = { error: null, previousPathname: this.props.pathname }
   }
 
-static getDerivedStateFromError(error: Error) {
+  static getDerivedStateFromError(error: Error) {
     if (isNextRouterError(error)) {
       // Re-throw if an expected internal Next.js router error occurs
       // this means it should be handled by a different boundary (such as a NotFound boundary in a parent segment)
       throw error
     }
 
-    // Report error to active span for OTEL tracing
-    if (typeof window !== 'undefined' && (globalThis as any).otel) {
-      try {
-static getDerivedStateFromProps(
+    return { error }
+  }
+
+  static getDerivedStateFromProps(
     props: ErrorBoundaryHandlerProps,
     state: ErrorBoundaryHandlerState
   ): ErrorBoundaryHandlerState | null {
@@ -90,23 +90,16 @@ static getDerivedStateFromProps(
       previousPathname: props.pathname,
     }
   }
-     * Approach of setState in render is safe as it checks the previous pathname and then overrides
-() => {
+
+  reset = () => {
     this.setState({ error: null })
-    if (this.state.error) {
-      queueMicrotask(() => {
-        if (typeof reportError === 'function') {
-render(): React.ReactNode {
+  }
+
+  // Explicit type is needed to avoid the generated `.d.ts` having a wide return type that could be specific to the `@types/react` version.
+  render(): React.ReactNode {
     //When it's bot request, segment level error boundary will keep rendering the children,
     // the final error will be caught by the root error boundary and determine wether need to apply graceful degrade.
     if (this.state.error && !isBotUserAgent) {
-      if (typeof window === 'undefined' && process.env.NEXT_RUNTIME === 'nodejs') {
-        const { trace } = require('@opentelemetry/api')
-        const span = trace.getActiveSpan()
-        if (span) {
-          span.recordException(this.state.error)
-        }
-      }
       return (
         <>
           <HandleISRError error={this.state.error} />
@@ -122,39 +115,12 @@ render(): React.ReactNode {
 
     return this.props.children
   }
-
-  // Explicit type is needed to avoid the generated `.d.ts` having a wide return type that could be specific to the `@types/react` version.
-  render(): React.ReactNode {
-    //When it's bot request, segment level error boundary will keep rendering the children,
-export function ErrorBoundary({
-  errorComponent,
-  errorStyles,
-  errorScripts,
-  children,
-}: ErrorBoundaryProps & {
-  children: React.ReactNode
-}): JSX.Element {
-  // When we're rendering the missing params shell, this will return null. This
-  // is because we won't be rendering any not found boundaries or error
-  // boundaries for the missing params shell. When this runs on the client
-  // (where these errors can occur), we will get the correct pathname.
-  const pathname = useUntrackedPathname()
-  if (errorComponent) {
-    return (
-      <ErrorBoundaryHandler
-        pathname={pathname}
-        errorComponent={errorComponent}
-        errorStyles={errorStyles}
-        errorScripts={errorScripts}
-        key={pathname}
-      >
-        {children}
-      </ErrorBoundaryHandler>
-    )
-  }
-
-  return <>{children}</>
 }
+
+/**
+ * Renders error boundary with the provided "errorComponent" property as the fallback.
+ * If no "errorComponent" property is provided it renders the children without an error boundary.
+ */
 export function ErrorBoundary({
   errorComponent,
   errorStyles,

Analysis

ErrorBoundaryHandler class has severe structural corruption with incomplete method definitions and duplicate declarations

What fails: packages/next/src/client/components/error-boundary.tsx fails to compile due to malformed ErrorBoundaryHandler class with incomplete getDerivedStateFromError method, missing reset method, orphaned code fragments, and duplicate ErrorBoundary function declarations.

How to reproduce:

cd packages/next
pnpm exec tsc --noEmit src/client/components/error-boundary.tsx

Result: TypeScript compiler fails with syntax errors - getDerivedStateFromError method starts with try { block at line 55 but immediately transitions to static getDerivedStateFromProps without proper closure, orphaned incomplete code at lines 96-99 with stray () => { fragments, duplicate render() method signatures at lines 127-129, and duplicate ErrorBoundary function declarations.

Expected: File should compile successfully and match the structure from commit dcece12, with complete method definitions: getDerivedStateFromError, getDerivedStateFromProps, reset, single render() method, and single ErrorBoundary function.

The file was corrupted by commit 5b50bad ("modify: packages/next/src/client/components/error-boundary.tsx - Issue #86517") which attempted to add OTEL tracing support but left the file in an incomplete, syntactically invalid state.

if (isNextRouterError(error)) {
// Re-throw if an expected internal Next.js router error occurs
// this means it should be handled by a different boundary (such as a NotFound boundary in a parent segment)
throw error
}

return { error }
}

static getDerivedStateFromProps(
// Report error to active span for OTEL tracing
if (typeof window !== 'undefined' && (globalThis as any).otel) {
try {
static getDerivedStateFromProps(
props: ErrorBoundaryHandlerProps,
state: ErrorBoundaryHandlerState
): ErrorBoundaryHandlerState | null {
Expand Down Expand Up @@ -90,16 +90,23 @@ export class ErrorBoundaryHandler extends React.Component<
previousPathname: props.pathname,
}
}

reset = () => {
* Approach of setState in render is safe as it checks the previous pathname and then overrides
() => {
this.setState({ error: null })
}

// Explicit type is needed to avoid the generated `.d.ts` having a wide return type that could be specific to the `@types/react` version.
render(): React.ReactNode {
if (this.state.error) {
queueMicrotask(() => {
if (typeof reportError === 'function') {
render(): React.ReactNode {
//When it's bot request, segment level error boundary will keep rendering the children,
// the final error will be caught by the root error boundary and determine wether need to apply graceful degrade.
if (this.state.error && !isBotUserAgent) {
if (typeof window === 'undefined' && process.env.NEXT_RUNTIME === 'nodejs') {
const { trace } = require('@opentelemetry/api')
const span = trace.getActiveSpan()
if (span) {
span.recordException(this.state.error)
}
}
return (
<>
<HandleISRError error={this.state.error} />
Expand All @@ -115,17 +122,39 @@ export class ErrorBoundaryHandler extends React.Component<

return this.props.children
}
}

/**
* Handles errors through `getDerivedStateFromError`.
* Renders the provided error component and provides a way to `reset` the error boundary state.
*/
// Explicit type is needed to avoid the generated `.d.ts` having a wide return type that could be specific to the `@types/react` version.
render(): React.ReactNode {
//When it's bot request, segment level error boundary will keep rendering the children,
export function ErrorBoundary({
errorComponent,
errorStyles,
errorScripts,
children,
}: ErrorBoundaryProps & {
children: React.ReactNode
}): JSX.Element {
// When we're rendering the missing params shell, this will return null. This
// is because we won't be rendering any not found boundaries or error
// boundaries for the missing params shell. When this runs on the client
// (where these errors can occur), we will get the correct pathname.
const pathname = useUntrackedPathname()
if (errorComponent) {
return (
<ErrorBoundaryHandler
pathname={pathname}
errorComponent={errorComponent}
errorStyles={errorStyles}
errorScripts={errorScripts}
key={pathname}
>
{children}
</ErrorBoundaryHandler>
)
}

/**
* Renders error boundary with the provided "errorComponent" property as the fallback.
* If no "errorComponent" property is provided it renders the children without an error boundary.
*/
return <>{children}</>
}
export function ErrorBoundary({
errorComponent,
errorStyles,
Expand Down
Loading
Loading