Skip to content

[bug] Watch Party: a host pause sent in a state report leaves the room playing #1676

Description

@neurekadev

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

  1. Start a Watch Party with a host and at least one guest, and start playback.
  2. 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.
  3. Wait for a guest to drift from the room position, a member to re-attach, or a guest to stall.
  4. 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

  • iOS/tvOS/macOS
  • Other/not client-specific

Relevant logs

no logs available

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

  • I reproduced this myself on a real deployment
  • Any logs provided are raw apart from marked redactions and are not AI-summarized; if none were available, I said so above

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions