diff --git a/packages/react-reconciler/src/ReactFiberThrow.new.js b/packages/react-reconciler/src/ReactFiberThrow.new.js
index 5a01005c25537..5b07409a7729f 100644
--- a/packages/react-reconciler/src/ReactFiberThrow.new.js
+++ b/packages/react-reconciler/src/ReactFiberThrow.new.js
@@ -41,7 +41,6 @@ import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.new';
 import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode';
 import {
   enableDebugTracing,
-  enableSchedulingProfiler,
   enableLazyContextPropagation,
   enableUpdaterTracking,
   enablePersistentOffscreenHostContainer,
@@ -71,10 +70,6 @@ import {
 import {propagateParentContextChangesToDeferredTree} from './ReactFiberNewContext.new';
 import {logCapturedError} from './ReactFiberErrorLogger';
 import {logComponentSuspended} from './DebugTracing';
-import {
-  markComponentRenderStopped,
-  markComponentSuspended,
-} from './SchedulingProfiler';
 import {isDevToolsPresent} from './ReactFiberDevToolsHook.new';
 import {
   SyncLane,
@@ -247,11 +242,6 @@ function throwException(
       }
     }
 
-    if (enableSchedulingProfiler) {
-      markComponentRenderStopped();
-      markComponentSuspended(sourceFiber, wakeable, rootRenderLanes);
-    }
-
     // Reset the memoizedState to what it was before we attempted to render it.
     // A legacy mode Suspense quirk, only relevant to hook components.
     const tag = sourceFiber.tag;
diff --git a/packages/react-reconciler/src/ReactFiberThrow.old.js b/packages/react-reconciler/src/ReactFiberThrow.old.js
index 6e060108c88ec..dcba4b521aebc 100644
--- a/packages/react-reconciler/src/ReactFiberThrow.old.js
+++ b/packages/react-reconciler/src/ReactFiberThrow.old.js
@@ -41,7 +41,6 @@ import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.old';
 import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode';
 import {
   enableDebugTracing,
-  enableSchedulingProfiler,
   enableLazyContextPropagation,
   enableUpdaterTracking,
   enablePersistentOffscreenHostContainer,
@@ -71,10 +70,6 @@ import {
 import {propagateParentContextChangesToDeferredTree} from './ReactFiberNewContext.old';
 import {logCapturedError} from './ReactFiberErrorLogger';
 import {logComponentSuspended} from './DebugTracing';
-import {
-  markComponentRenderStopped,
-  markComponentSuspended,
-} from './SchedulingProfiler';
 import {isDevToolsPresent} from './ReactFiberDevToolsHook.old';
 import {
   SyncLane,
@@ -247,11 +242,6 @@ function throwException(
       }
     }
 
-    if (enableSchedulingProfiler) {
-      markComponentRenderStopped();
-      markComponentSuspended(sourceFiber, wakeable, rootRenderLanes);
-    }
-
     // Reset the memoizedState to what it was before we attempted to render it.
     // A legacy mode Suspense quirk, only relevant to hook components.
     const tag = sourceFiber.tag;
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
index ac420850fae82..dbeb72b856326 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
@@ -68,6 +68,9 @@ import {
 import {
   markCommitStarted,
   markCommitStopped,
+  markComponentRenderStopped,
+  markComponentSuspended,
+  markComponentErrored,
   markLayoutEffectsStarted,
   markLayoutEffectsStopped,
   markPassiveEffectsStarted,
@@ -1356,6 +1359,29 @@ function handleError(root, thrownValue): void {
         stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true);
       }
 
+      if (enableSchedulingProfiler) {
+        markComponentRenderStopped();
+
+        if (
+          thrownValue !== null &&
+          typeof thrownValue === 'object' &&
+          typeof thrownValue.then === 'function'
+        ) {
+          const wakeable: Wakeable = (thrownValue: any);
+          markComponentSuspended(
+            erroredWork,
+            wakeable,
+            workInProgressRootRenderLanes,
+          );
+        } else {
+          markComponentErrored(
+            erroredWork,
+            thrownValue,
+            workInProgressRootRenderLanes,
+          );
+        }
+      }
+
       throwException(
         root,
         erroredWork.return,
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
index c98c7abac71fe..af9e293d712a7 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
@@ -68,6 +68,9 @@ import {
 import {
   markCommitStarted,
   markCommitStopped,
+  markComponentRenderStopped,
+  markComponentSuspended,
+  markComponentErrored,
   markLayoutEffectsStarted,
   markLayoutEffectsStopped,
   markPassiveEffectsStarted,
@@ -1356,6 +1359,29 @@ function handleError(root, thrownValue): void {
         stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true);
       }
 
+      if (enableSchedulingProfiler) {
+        markComponentRenderStopped();
+
+        if (
+          thrownValue !== null &&
+          typeof thrownValue === 'object' &&
+          typeof thrownValue.then === 'function'
+        ) {
+          const wakeable: Wakeable = (thrownValue: any);
+          markComponentSuspended(
+            erroredWork,
+            wakeable,
+            workInProgressRootRenderLanes,
+          );
+        } else {
+          markComponentErrored(
+            erroredWork,
+            thrownValue,
+            workInProgressRootRenderLanes,
+          );
+        }
+      }
+
       throwException(
         root,
         erroredWork.return,
diff --git a/packages/react-reconciler/src/SchedulingProfiler.js b/packages/react-reconciler/src/SchedulingProfiler.js
index b4e7f83d3a157..9b0985cf46139 100644
--- a/packages/react-reconciler/src/SchedulingProfiler.js
+++ b/packages/react-reconciler/src/SchedulingProfiler.js
@@ -144,6 +144,33 @@ export function markComponentRenderStopped(): void {
   }
 }
 
+export function markComponentErrored(
+  fiber: Fiber,
+  thrownValue: mixed,
+  lanes: Lanes,
+): void {
+  if (enableSchedulingProfiler) {
+    if (supportsUserTimingV3) {
+      const componentName = getComponentNameFromFiber(fiber) || 'Unknown';
+      const phase = fiber.alternate === null ? 'mount' : 'update';
+
+      let message = '';
+      if (
+        thrownValue !== null &&
+        typeof thrownValue === 'object' &&
+        typeof thrownValue.message === 'string'
+      ) {
+        message = thrownValue.message;
+      } else if (typeof thrownValue === 'string') {
+        message = thrownValue;
+      }
+
+      // TODO (scheduling profiler) Add component stack id
+      markAndClear(`--error-${componentName}-${phase}-${message}`);
+    }
+  }
+}
+
 const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
 
 // $FlowFixMe: Flow cannot handle polymorphic WeakMaps
diff --git a/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js b/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js
index 8680d19b710bf..47768c52a88d9 100644
--- a/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js
@@ -715,4 +715,143 @@ describe('SchedulingProfiler', () => {
     `);
     }
   });
+
+  it('should mark sync render that throws', async () => {
+    class ErrorBoundary extends React.Component {
+      state = {error: null};
+      componentDidCatch(error) {
+        this.setState({error});
+      }
+      render() {
+        if (this.state.error) {
+          return null;
+        }
+        return this.props.children;
+      }
+    }
+
+    function ExampleThatThrows() {
+      throw Error('Expected error');
+    }
+
+    ReactTestRenderer.create(
+      <ErrorBoundary>
+        <ExampleThatThrows />
+      </ErrorBoundary>,
+    );
+
+    if (gate(flags => flags.enableSchedulingProfiler)) {
+      expect(getMarks()).toMatchInlineSnapshot(`
+      Array [
+        "--schedule-render-1",
+        "--render-start-1",
+        "--component-render-start-ErrorBoundary",
+        "--component-render-stop",
+        "--component-render-start-ExampleThatThrows",
+        "--component-render-start-ExampleThatThrows",
+        "--component-render-stop",
+        "--error-ExampleThatThrows-mount-Expected error",
+        "--render-stop",
+        "--commit-start-1",
+        "--react-version-17.0.3",
+        "--profiler-version-1",
+        "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen",
+        "--layout-effects-start-1",
+        "--schedule-state-update-1-ErrorBoundary",
+        "--layout-effects-stop",
+        "--commit-stop",
+        "--render-start-1",
+        "--component-render-start-ErrorBoundary",
+        "--component-render-stop",
+        "--render-stop",
+        "--commit-start-1",
+        "--react-version-17.0.3",
+        "--profiler-version-1",
+        "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen",
+        "--commit-stop",
+      ]
+    `);
+    }
+  });
+
+  it('should mark concurrent render that throws', async () => {
+    spyOnProd(console, 'error');
+
+    class ErrorBoundary extends React.Component {
+      state = {error: null};
+      componentDidCatch(error) {
+        this.setState({error});
+      }
+      render() {
+        if (this.state.error) {
+          return null;
+        }
+        return this.props.children;
+      }
+    }
+
+    function ExampleThatThrows() {
+      // eslint-disable-next-line no-throw-literal
+      throw 'Expected error';
+    }
+
+    ReactTestRenderer.create(
+      <ErrorBoundary>
+        <ExampleThatThrows />
+      </ErrorBoundary>,
+      {unstable_isConcurrent: true},
+    );
+
+    if (gate(flags => flags.enableSchedulingProfiler)) {
+      expect(getMarks()).toMatchInlineSnapshot(`
+      Array [
+        "--schedule-render-16",
+      ]
+    `);
+    }
+
+    clearPendingMarks();
+
+    expect(Scheduler).toFlushUntilNextPaint([]);
+
+    if (gate(flags => flags.enableSchedulingProfiler)) {
+      expect(getMarks()).toMatchInlineSnapshot(`
+        Array [
+          "--render-start-16",
+          "--component-render-start-ErrorBoundary",
+          "--component-render-stop",
+          "--component-render-start-ExampleThatThrows",
+          "--component-render-start-ExampleThatThrows",
+          "--component-render-stop",
+          "--error-ExampleThatThrows-mount-Expected error",
+          "--render-stop",
+          "--render-start-16",
+          "--component-render-start-ErrorBoundary",
+          "--component-render-stop",
+          "--component-render-start-ExampleThatThrows",
+          "--component-render-start-ExampleThatThrows",
+          "--component-render-stop",
+          "--error-ExampleThatThrows-mount-Expected error",
+          "--render-stop",
+          "--commit-start-16",
+          "--react-version-17.0.3",
+          "--profiler-version-1",
+          "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen",
+          "--layout-effects-start-16",
+          "--schedule-state-update-1-ErrorBoundary",
+          "--layout-effects-stop",
+          "--render-start-1",
+          "--component-render-start-ErrorBoundary",
+          "--component-render-stop",
+          "--render-stop",
+          "--commit-start-1",
+          "--react-version-17.0.3",
+          "--profiler-version-1",
+          "--react-lane-labels-Sync,InputContinuousHydration,InputContinuous,DefaultHydration,Default,TransitionHydration,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Transition,Retry,Retry,Retry,Retry,Retry,SelectiveHydration,IdleHydration,Idle,Offscreen",
+          "--commit-stop",
+          "--commit-stop",
+        ]
+      `);
+    }
+  });
 });