You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two people edit a post that already has saved content. One of them closes the editor, and later opens the post again. Sometimes, right after they come back, one of the saved paragraphs appears twice in both windows, and another saved paragraph is gone. This happens with the DE-RTC engine over the WebSocket transport. The same fuzzer seed passes over short polling and over SSE.
Example
Start the tests environment (npm run env:tests start).
Run the fuzzer's default five seeds on this pair: npm run fuzz -- --combos=de-rtc/websocket.
Seed 5 fails. It failed like this in two of two sweeps. Both times, the automatic rerun of seed 5 on its own passed.
What you see:Error: markers duplicated in converged content after step 7, with "f5s9001u0-pre": 2. Both windows agree on the content. The paragraph f5s9001u0-pre shows twice, one after the other, and f5s9000u0-pre is missing from the editor.
What you expected: both saved paragraphs (f5s9000u0-pre and f5s9001u0-pre) appear once each, in both windows.
What should happen instead
When someone opens a post again while a collaborator is still editing it, they should see the same content that collaborator sees. No paragraph should be copied, and none should be lost.
How we will know it is done
foriin$(seq 10);do npm run fuzz -- --combos=de-rtc/websocket --seeds=5 --no-recheck;done
All ten runs pass every seed. This runs seeds 1-5 in one sweep, the way the failure was found (seed 5 alone passed on the rerun). Then npm run fuzz -- --engines=de-rtc passes on all three transports, with no flaky seeds.
Seed 5 is the "existing post" variant (seed % 3 === 2): before the shared session, user 0 opens the post alone, adds f5s9000u0-pre and f5s9001u0-pre at the end, saves, and leaves. So both paragraphs are in the saved post before anyone collaborates.
The trace, identical in both failing runs: step 0 concurrent-same-block-edit on paragraph 1 (user 1's text was parked; the card "Pending content: Beta paragraph f5s100u1-csb" is still showing at the end), step 1 user 1 leaves and user 0 inserts f5s101u0-ins, step 2 undo, step 3 insert-heading, step 4 insert-list, step 5 move-block (index 7, up), step 6 undo, step 7 user 1 rejoins, adds f5s7u1-rejoin, then deep-nest-group.
The duplicate check runs after every step, and steps 0-6 passed it. So the duplicate appeared during step 7: the rejoin, the rejoiner's insert, or the deep-nest-group. The check does not look for missing markers, so f5s9000u0-pre may have been lost earlier (for example by the step 5 move and step 6 undo). Find out which step lost it before guessing at the cause.
One idea, NOT confirmed: the rejoining editor starts from the saved post (which has both paragraphs at their saved positions), while the live room has moved blocks since. If the rejoiner's blocks are lined up with the room's blocks by position rather than by metadata.syncId, a moved block could be matched with the wrong neighbor. See WP_De_RTC_Identity_Merge and adopt() in WP_De_RTC_Block_Identity, and the "Incorporate" path on the client.
Why only WebSocket: unknown. One difference in the fuzzer is that the sweep runs seeds 1-4 against the same long-running daemon before seed 5, while the recheck runs seed 5 on its own. The daemon caches options at boot. Also compare how a rejoining tab first receives the room's state over the socket versus over a poll.
Artifacts (local only, not committed): tests/fuzzer/artifacts/fuzz-2026-09-25-16-59-/de-rtc--websocket/ and tests/fuzzer/artifacts/fuzz-2026-09-25-17-14-/de-rtc--websocket/ (error-context.md, trace.zip, and the fuzz-run.json step log in the sweep report). RTC_FUZZ_LOG_SYNC=1 adds per-request wire summaries on a rerun.
What happens now
Two people edit a post that already has saved content. One of them closes the editor, and later opens the post again. Sometimes, right after they come back, one of the saved paragraphs appears twice in both windows, and another saved paragraph is gone. This happens with the DE-RTC engine over the WebSocket transport. The same fuzzer seed passes over short polling and over SSE.
Example
npm run env:tests start).npm run fuzz -- --combos=de-rtc/websocket.What you see:
Error: markers duplicated in converged content after step 7, with"f5s9001u0-pre": 2. Both windows agree on the content. The paragraphf5s9001u0-preshows twice, one after the other, andf5s9000u0-preis missing from the editor.What you expected: both saved paragraphs (
f5s9000u0-preandf5s9001u0-pre) appear once each, in both windows.What should happen instead
When someone opens a post again while a collaborator is still editing it, they should see the same content that collaborator sees. No paragraph should be copied, and none should be lost.
How we will know it is done
All ten runs pass every seed. This runs seeds 1-5 in one sweep, the way the failure was found (seed 5 alone passed on the rerun). Then
npm run fuzz -- --engines=de-rtcpasses on all three transports, with no flaky seeds.Notes for whoever picks this up
npm run fuzz -- --engines=de-rtccheck for Fuzzer: a "pending" card can block the next click on DE-RTC #109 (PR Fuzzer: stop getting stuck behind DE-RTC's pending card #122). That PR does not cause it: the failing run has no review card and no click into a paragraph before step 7, and over WebSocket the fuzzer's discovery wait (the other change in Fuzzer: stop getting stuck behind DE-RTC's pending card #122) returns before any changed code runs. An independent run by the Fuzzer: a "pending" card can block the next click on DE-RTC #109 verifier failed the same way.seed % 3 === 2): before the shared session, user 0 opens the post alone, addsf5s9000u0-preandf5s9001u0-preat the end, saves, and leaves. So both paragraphs are in the saved post before anyone collaborates.f5s101u0-ins, step 2 undo, step 3 insert-heading, step 4 insert-list, step 5 move-block (index 7, up), step 6 undo, step 7 user 1 rejoins, addsf5s7u1-rejoin, then deep-nest-group.f5s9000u0-premay have been lost earlier (for example by the step 5 move and step 6 undo). Find out which step lost it before guessing at the cause.metadata.syncId, a moved block could be matched with the wrong neighbor. SeeWP_De_RTC_Identity_Mergeandadopt()inWP_De_RTC_Block_Identity, and the "Incorporate" path on the client.tests/fuzzer/artifacts/fuzz-2026-09-25-16-59-/de-rtc--websocket/andtests/fuzzer/artifacts/fuzz-2026-09-25-17-14-/de-rtc--websocket/(error-context.md,trace.zip, and thefuzz-run.jsonstep log in the sweep report).RTC_FUZZ_LOG_SYNC=1adds per-request wire summaries on a rerun.