Repository: facebook/react
Pull request: [fiber] bugfix - don't show <Offscreen> in error message.

## Overview

While building the RSC sandboxes I notice error messages like:

>  An error occurred in the `<Offscreen>` component

This is an internal component so it should show either:

>  An error occurred in the `<Suspense>` component.

>  An error occurred in the `<Activity>` component.

It should only happen when there's a lazy in the direct child position of a `<Suspense>` or `<Activity>` component.

Changed files:
filename: packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js
patch: @@ -213,6 +213,67 @@ describe('ReactIncrementalErrorLogging', () => {
     }).toThrow('logCapturedError error');
   });
 
+  it('does not report internal Offscreen component for errors thrown during reconciliation inside Suspense', async () => {
+    // When a child of Suspense throws during reconciliation (not render),
+    // a Throw fiber is created whose .return is the internal Offscreen fiber.
+    // We should skip Offscreen since it's an internal
+    // implementation detail and walk up to Suspense instead.
+    const lazyChild = React.lazy(() => {
+      throw new Error('lazy init error');
+    });
+
+    await fakeAct(() => {
+      ReactNoop.render(
+        <React.Suspense fallback={<div />}>{lazyChild}</React.Suspense>,
+      );
+    });
+    expect(uncaughtExceptionMock).toHaveBeenCalledTimes(1);
+    expect(uncaughtExceptionMock).toHaveBeenCalledWith(
+      expect.objectContaining({
+        message: 'lazy init error',
+      }),
+    );
+    if (__DEV__) {
+      expect(console.warn).toHaveBeenCalledTimes(1);
+      expect(console.warn.mock.calls[0]).toEqual([
+        '%s\n\n%s\n',
+        'An error occurred in the <Suspense> component.',
+        'Consider adding an error boundary to your tree to customize error handling behavior.\n' +
+          'Visit https://react.dev/link/error-boundaries to learn more about error boundaries.',
+      ]);
+    }
+  });
+
+  it('does not report internal Offscreen component for errors thrown during reconciliation inside Activity', async () => {
+    // Same as the Suspense test above — Activity also wraps its children in
+    // an internal Offscreen fiber. The error message should show Activity,
+    // not Offscreen.
+    const lazyChild = React.lazy(() => {
+      throw new Error('lazy init error');
+    });
+
+    await fakeAct(() => {
+      ReactNoop.render(
+        <React.Activity mode="visible">{lazyChild}</React.Activity>,
+      );
+    });
+    expect(uncaughtExceptionMock).toHaveBeenCalledTimes(1);
+    expect(uncaughtExceptionMock).toHaveBeenCalledWith(
+      expect.objectContaining({
+        message: 'lazy init error',
+      }),
+    );
+    if (__DEV__) {
+      expect(console.warn).toHaveBeenCalledTimes(1);
+      expect(console.warn.mock.calls[0]).toEqual([
+        '%s\n\n%s\n',
+        'An error occurred in the <Activity> component.',
+        'Consider adding an error boundary to your tree to customize error handling behavior.\n' +
+          'Visit https://react.dev/link/error-boundaries to learn more about error boundaries.',
+      ]);
+    }
+  });
+
   it('resets instance variables before unmounting failed node', async () => {
     class ErrorBoundary extends React.Component {
       state = {error: null};

filename: packages/react-reconciler/src/getComponentNameFromFiber.js
patch: @@ -122,7 +122,10 @@ export default function getComponentNameFromFiber(fiber: Fiber): string | null {
       }
       return 'Mode';
     case OffscreenComponent:
-      return 'Offscreen';
+      if (fiber.return !== null) {
+        return getComponentNameFromFiber(fiber.return);
+      }
+      return null;
     case Profiler:
       return 'Profiler';
     case ScopeComponent: