From 7d71150439aa7cefc1d9a828cb63b4db790cf0d9 Mon Sep 17 00:00:00 2001 From: Keysat Date: Fri, 8 May 2026 11:04:50 -0500 Subject: [PATCH] Fix SSE event type lost across reader chunks (blank screen post-process) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symptom: after a long video finishes processing, the screen goes blank even though the video and chunks save correctly to history (visible after a refresh + library click). Cause: the manual SSE parser in processUrl declared `let eventType = ""` inside the `while (await reader.read())` loop, so the variable reset on every chunk. The server emits each event as a single write of `event: X\ndata: Y\n\n`, but for a long video the result payload (entries + chunks + logs) is tens of KB and gets split across reader chunks by the browser. When the split landed between the `event: result\n` line and the `data: ...` line, the event type was lost and `handleSSE("", data)` matched no branch — the result event was silently dropped, and state.chunks stayed at the empty array set during processUrl reset. Fix: hoist eventType outside the loop so it persists across chunks, and reset it after each dispatch (per the SSE spec, event type returns to default after an event is fired). Short videos with small result payloads fit in a single chunk and so were unaffected — which is why the bug looked intermittent. --- public/index.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 3801202..94cb33e 100644 --- a/public/index.html +++ b/public/index.html @@ -1428,6 +1428,13 @@ const reader = res.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; + // Persist eventType across reader chunks. SSE events are + // `event: X\ndata: Y\n\n`, but a single TCP/fetch chunk can split + // between those two lines — when that happens, we'd lose the event + // type and silently drop the event (e.g. the final `result` for a + // long video, where the payload is tens of KB). Reset only after + // dispatch, per the SSE spec. + let eventType = ""; while (true) { const { done, value } = await reader.read(); @@ -1437,13 +1444,13 @@ const lines = buffer.split("\n"); buffer = lines.pop() || ""; - let eventType = ""; for (const line of lines) { if (line.startsWith("event: ")) { eventType = line.slice(7); } else if (line.startsWith("data: ")) { const data = JSON.parse(line.slice(6)); handleSSE(eventType, data); + eventType = ""; } } }