Skip to content

[DevTools] Don't capture durations for disconnected subtrees when profiling#35718

Merged
hoxyq merged 1 commit intomainfrom
devtools/dont-capture-durations-for-disconnected-subtrees
Feb 9, 2026
Merged

[DevTools] Don't capture durations for disconnected subtrees when profiling#35718
hoxyq merged 1 commit intomainfrom
devtools/dont-capture-durations-for-disconnected-subtrees

Conversation

@hoxyq
Copy link
Contributor

@hoxyq hoxyq commented Feb 7, 2026

After #34089, when updating (possibly, mounting) inside disconnected subtree, we don't record this as an operation. This only happens during reconnect. The issue is that recordProfilingDurations() can be called, which diffs tree base duration and reports it to the Frontend:

if (isProfiling) {
// It's important to update treeBaseDuration even if the current Fiber did not render,
// because it's possible that one of its descendants did.
if (
prevFiber == null ||
treeBaseDuration !== prevFiber.treeBaseDuration
) {
// Tree base duration updates are included in the operations typed array.
// So we have to convert them from milliseconds to microseconds so we can send them as ints.
const convertedTreeBaseDuration = Math.floor(
(treeBaseDuration || 0) * 1000,
);
pushOperation(TREE_OPERATION_UPDATE_TREE_BASE_DURATION);
pushOperation(id);
pushOperation(convertedTreeBaseDuration);
}

This operation can be recorded before the "Add" operation, and it will not be resolved properly on the Frontend side.

Before the fix:

commit tree › Suspense › should handle transitioning from fallback back to content during profiling

    Could not clone the node: commit tree does not contain fiber "5". This is a bug in React DevTools.

      162 |     const existingNode = nodes.get(id);
      163 |     if (existingNode == null) {
    > 164 |       throw new Error(
          |             ^
      165 |         `Could not clone the node: commit tree does not contain fiber "${id}". This is a bug in React DevTools.`,
      166 |       );
      167 |     }

      at getClonedNode (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:164:13)
      at updateTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:348:24)
      at getCommitTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:112:20)
      at ProfilingCache.getCommitTree (packages/react-devtools-shared/src/devtools/ProfilingCache.js:40:46)
      at Object.<anonymous> (packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js:257:44)

@afurm
Copy link

afurm commented Feb 8, 2026

LGTM. Skipping profiling duration capture for disconnected subtrees seems right, and the added Suspense coverage is a good regression test (fallback → primary transition during profiling).

No other nits from me.

@hoxyq hoxyq merged commit c6bb26b into main Feb 9, 2026
240 checks passed
@hoxyq hoxyq deleted the devtools/dont-capture-durations-for-disconnected-subtrees branch February 9, 2026 22:18
github-actions bot pushed a commit to code/lib-react that referenced this pull request Feb 15, 2026
…filing (facebook#35718)

After facebook#34089, when updating
(possibly, mounting) inside disconnected subtree, we don't record this
as an operation. This only happens during reconnect. The issue is that
`recordProfilingDurations()` can be called, which diffs tree base
duration and reports it to the Frontend:

https://github.com/facebook/react/blob/65db1000b944c8a07b5947c06b38eb8364dce4f2/packages/react-devtools-shared/src/backend/fiber/renderer.js#L4506-L4521

This operation can be recorded before the "Add" operation, and it will
not be resolved properly on the Frontend side.

Before the fix:
```
commit tree › Suspense › should handle transitioning from fallback back to content during profiling

    Could not clone the node: commit tree does not contain fiber "5". This is a bug in React DevTools.

      162 |     const existingNode = nodes.get(id);
      163 |     if (existingNode == null) {
    > 164 |       throw new Error(
          |             ^
      165 |         `Could not clone the node: commit tree does not contain fiber "${id}". This is a bug in React DevTools.`,
      166 |       );
      167 |     }

      at getClonedNode (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:164:13)
      at updateTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:348:24)
      at getCommitTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:112:20)
      at ProfilingCache.getCommitTree (packages/react-devtools-shared/src/devtools/ProfilingCache.js:40:46)
      at Object.<anonymous> (packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js:257:44)
```

DiffTrain build for [c6bb26b](facebook@c6bb26b)
github-actions bot pushed a commit to code/lib-react that referenced this pull request Feb 15, 2026
…filing (facebook#35718)

After facebook#34089, when updating
(possibly, mounting) inside disconnected subtree, we don't record this
as an operation. This only happens during reconnect. The issue is that
`recordProfilingDurations()` can be called, which diffs tree base
duration and reports it to the Frontend:

https://github.com/facebook/react/blob/65db1000b944c8a07b5947c06b38eb8364dce4f2/packages/react-devtools-shared/src/backend/fiber/renderer.js#L4506-L4521

This operation can be recorded before the "Add" operation, and it will
not be resolved properly on the Frontend side.

Before the fix:
```
commit tree › Suspense › should handle transitioning from fallback back to content during profiling

    Could not clone the node: commit tree does not contain fiber "5". This is a bug in React DevTools.

      162 |     const existingNode = nodes.get(id);
      163 |     if (existingNode == null) {
    > 164 |       throw new Error(
          |             ^
      165 |         `Could not clone the node: commit tree does not contain fiber "${id}". This is a bug in React DevTools.`,
      166 |       );
      167 |     }

      at getClonedNode (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:164:13)
      at updateTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:348:24)
      at getCommitTree (packages/react-devtools-shared/src/devtools/views/Profiler/CommitTreeBuilder.js:112:20)
      at ProfilingCache.getCommitTree (packages/react-devtools-shared/src/devtools/ProfilingCache.js:40:46)
      at Object.<anonymous> (packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js:257:44)
```

DiffTrain build for [c6bb26b](facebook@c6bb26b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants