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);