From 4536d27ad2834a94e945e8935e948e61452b909a Mon Sep 17 00:00:00 2001 From: claude code agent 227 Date: Sat, 20 Jun 2026 21:42:30 +0300 Subject: [PATCH] fix(page-templates): never strand a page-embed id in-flight (#35) In the page-embed lookup flush(), the success branch cleared inFlightRef and resolved waiters only for ids present in the response items. A short/partial server response would leave a requested id stuck in inFlightRef forever (the subscribe/refresh path is guarded by !inFlightRef.has(id)) and its refresh() promise would never resolve. After processing returned items, also clear + resolve any requested id that wasn't returned, mirroring the catch branch. Cannot trigger under today's exact-mapping server contract; this is hardening. Co-Authored-By: Claude Opus 4.8 --- .../page-embed/page-embed-lookup-context.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/client/src/features/editor/components/page-embed/page-embed-lookup-context.tsx b/apps/client/src/features/editor/components/page-embed/page-embed-lookup-context.tsx index aa2a8caf..d29c19dc 100644 --- a/apps/client/src/features/editor/components/page-embed/page-embed-lookup-context.tsx +++ b/apps/client/src/features/editor/components/page-embed/page-embed-lookup-context.tsx @@ -55,7 +55,9 @@ export function PageEmbedLookupProvider({ try { const { items } = await lookupTemplate({ sourcePageIds: ids }); + const returned = new Set(); for (const r of items) { + returned.add(r.sourcePageId); resultCacheRef.current.set(r.sourcePageId, r); inFlightRef.current.delete(r.sourcePageId); const subs = subscribersRef.current.get(r.sourcePageId); @@ -64,6 +66,17 @@ export function PageEmbedLookupProvider({ } resolveWaiters(r.sourcePageId); } + // Harden against a partial/short server response: any requested id not + // present in `items` would otherwise stay in `inFlightRef` forever + // (subscribe/refresh are guarded by `!inFlightRef.has(id)`) and its + // refresh() promise would never resolve. Clear + resolve those ids, + // mirroring the catch branch, so no id can be stranded in-flight. + for (const id of ids) { + if (!returned.has(id)) { + inFlightRef.current.delete(id); + resolveWaiters(id); + } + } } catch (err) { // Surface the failure: errors must never be swallowed silently. console.error("[pageEmbed] template lookup failed", err);