What happened
In a Watch Party, the host paused and the room did not stay paused: playback started again for members with nobody pressing Play.
The server stores a host pause in two ways. A transport_request sets the room's IsPaused, PlaybackState, and ResumeOnReady together. A host state_report that disagrees with the room is also accepted as the room's new state, but it updates only IsPaused; PlaybackState stays playing. Everything that chooses between play and pause reads PlaybackState, so after such a pause the server keeps sending play into the paused room:
- to a guest whose position drifts more than a second from the room,
- to any member that re-attaches, including the host after its periodic socket renewal,
- and when a guest stalls: the buffering barrier it arms is set to resume the room when everyone is ready.
A host pause reaches the server only as a state report whenever the client does not send it as a request. One known case: the Apple client drops a Play/Pause press while the room socket is reconnecting (Silo-Server/silo-apple#410), but the local player still pauses and the next state report carries is_paused: true.
Steps to reproduce
- Start a Watch Party with a host and at least one guest, and start playback.
- Pause on the host in a way the client reports only in a state report, for example while the host's room socket is reconnecting.
- Wait for a guest to drift from the room position, a member to re-attach, or a guest to stall.
- Playback starts again for that member, or for the room once the barrier clears.
Expected behavior
A room the host paused stays paused, and corrections and re-attach syncs send pause.
Silo version / commit
Found in main at 0eddbf9ed; the reproduction instance's exact build was not recorded.
Deployment
Not recorded for the reproduction instance.
Clients affected
Relevant logs
The reproduction ran on a separate instance and its server logs were not collected. On a server logging at debug level, the symptom is a watch together correction queued or watch together sync queued line with action=play playback_state=playing sent while the room is paused.
Technical notes
handleStateReportForConnection in internal/watchtogether/service.go accepts a host report as authoritative when it disagrees with the room's pause state, then sets live.room.IsPaused = report.IsPaused and leaves PlaybackState and ResumeOnReady unchanged.
- The guest correction in the same function,
syncMemberToRoomLocked, and the buffering barrier (PlaybackState == RoomPlaybackStatePlaying || ResumeOnReady) choose play or pause from those two fields.
- Separately, the authoritative report leaves the room's last transport command in place. After an explicit pause followed by a resume through a report, the reconciler can replay that pause to a member whose socket renews before it re-attaches.
Fix proposed in #1673.
AI harness
Claude Code (T3 Code)
AI tool(s)
Claude Code
AI model(s)
claude-opus-5-5
AI involvement
AI-assisted
Independent or adversarial review
n/a. The defect was found by reading the code and reproduced in a unit test; the reporter then reproduced the behavior on a separate instance.
Confirmations
What happened
In a Watch Party, the host paused and the room did not stay paused: playback started again for members with nobody pressing Play.
The server stores a host pause in two ways. A
transport_requestsets the room'sIsPaused,PlaybackState, andResumeOnReadytogether. A hoststate_reportthat disagrees with the room is also accepted as the room's new state, but it updates onlyIsPaused;PlaybackStatestaysplaying. Everything that chooses between play and pause readsPlaybackState, so after such a pause the server keeps sendingplayinto the paused room:A host pause reaches the server only as a state report whenever the client does not send it as a request. One known case: the Apple client drops a Play/Pause press while the room socket is reconnecting (Silo-Server/silo-apple#410), but the local player still pauses and the next state report carries
is_paused: true.Steps to reproduce
Expected behavior
A room the host paused stays paused, and corrections and re-attach syncs send
pause.Silo version / commit
Found in
mainat0eddbf9ed; the reproduction instance's exact build was not recorded.Deployment
Not recorded for the reproduction instance.
Clients affected
Relevant logs
The reproduction ran on a separate instance and its server logs were not collected. On a server logging at debug level, the symptom is a
watch together correction queuedorwatch together sync queuedline withaction=play playback_state=playingsent while the room is paused.Technical notes
handleStateReportForConnectionininternal/watchtogether/service.goaccepts a host report as authoritative when it disagrees with the room's pause state, then setslive.room.IsPaused = report.IsPausedand leavesPlaybackStateandResumeOnReadyunchanged.syncMemberToRoomLocked, and the buffering barrier (PlaybackState == RoomPlaybackStatePlaying || ResumeOnReady) choose play or pause from those two fields.Fix proposed in #1673.
AI harness
Claude Code (T3 Code)
AI tool(s)
Claude Code
AI model(s)
claude-opus-5-5
AI involvement
AI-assisted
Independent or adversarial review
n/a. The defect was found by reading the code and reproduced in a unit test; the reporter then reproduced the behavior on a separate instance.
Confirmations