Skip to content
Open
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
19 changes: 19 additions & 0 deletions apps/profiler-ui/src/views/ProfilerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,9 @@ const ProfilerView: React.FC<ProfilerViewProps> = ({ host, port, name }) => {
// Guard against stale async responses when target changes mid-flight
const fetchIdRef = useRef<number>(0);

// Guard so an existing server-side report is rehydrated at most once per target
const rehydratedTargetRef = useRef<string | null | undefined>(undefined);

// =========================================================================
// STATUS POLLING
// =========================================================================
Expand Down Expand Up @@ -546,6 +549,22 @@ const ProfilerView: React.FC<ProfilerViewProps> = ({ host, port, name }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showSystemCalls]);

// Rehydrate an existing report when this view mounts (or re-mounts) without
// local data — e.g. after the tab is split, which mounts fresh ProfilerView
// instances. Report DATA lives only in local state and is otherwise populated
// solely by the live Stop flow, so a fresh instance shows "No profiling data
// available" even though the server still holds a report (status.has_report
// stays true because it is server-backed). Fetch it once per target.
useEffect(() => {
if (!isConnected) { rehydratedTargetRef.current = undefined; return; }
if (status?.active === true) return; // a live session owns the data
if (!status?.has_report) return; // nothing on the server to rehydrate
if (treeData?.tree != null) return; // already have data locally
if (rehydratedTargetRef.current === target) return; // already attempted for this target
Comment on lines +559 to +563

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Rehydration guard can skip fetch for a newly selected target.

At Line 562, treeData is treated as globally valid, but target switches can leave stale local tree data from the previous target (Line 678 only changes target). That causes this effect to return early and not rehydrate the new target’s report.

💡 Proposed fix
@@
-				<select
+				<select
 					style={styles.select}
 					value={target || ''}
-					onChange={(e) => setTarget(e.target.value || null)}
+					onChange={(e) => {
+						const nextTarget = e.target.value || null;
+						setTarget(nextTarget);
+						// Clear local report state so rehydration can fetch for the new target
+						setReport('');
+						setTreeData(null);
+						setOriginalRoot(null);
+						setVizRoot(null);
+						setCallStack([]);
+						rehydratedTargetRef.current = undefined;
+					}}
 					disabled={isActive}
 				>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/profiler-ui/src/views/ProfilerView.tsx` around lines 559 - 563, The
guard condition at line 562 that checks if treeData?.tree exists doesn't account
for target switches. When a new target is selected, the existing treeData may be
stale data from the previous target, causing the effect to return early without
rehydrating the new target's data. Modify the guard condition to also verify
that the existing treeData corresponds to the current target, not just check if
treeData exists. This ensures that when switching to a new target, the effect
will properly proceed to rehydrate that target's report instead of skipping it
due to stale data from the previous target.

rehydratedTargetRef.current = target;
fetchReport();
}, [isConnected, status?.active, status?.has_report, target, treeData, fetchReport]);

// =========================================================================
// ROOT CHANGE HANDLER
// =========================================================================
Expand Down
Loading