Skip to content

A failed reconnect latches the client into HTTP mode forever — live updates stop until a full reload #160

Closed

Description

@adnaan

What happens

If the WebSocket drops and the reconnect attempt fails (phone asleep, Wi-Fi/tailnet blip, laptop lid), the client switches to HTTP mode and never tries the WebSocket again. HTTP mode gets no server push, so the page shows stale state until the user reloads.

Seen in prereview on a phone: a live status indicator only updated after a manual refresh. The server log showed the phone's WS connections cycling, then nothing at all for ~10 minutes until the reload.

Reproduction (v0.25.1, chromedp, no reload)

  1. Open a live page; the WS connects and pushes work.
  2. network.EmulateNetworkConditions(offline=true).
  3. Change server state while offline.
  4. Go back online and wait 40s.

Console:

Heartbeat: socket dead (pong timeout) — reconnecting
WebSocket open failed, falling back to HTTP
Failed to fetch initial state:

After step 4 the DOM never updates and no new WS opens. A reload fixes it.

Cause

  • performVisibilityReconnect (livetemplate-client.ts:992) sets this.useHTTP = !result.usingWebSocket. A connect that fails because the network is down goes through the catch in transport/websocket.ts:274 ("falling back to HTTP"), so useHTTP becomes true.
  • Both self-healing paths skip HTTP mode:
    • heartbeatTick (:1036) returns early on this.useHTTP.
    • The visibility handler (:962) requires !this.useHTTP.

So nothing ever retries the WebSocket again.

The HTTP fallback exists for "this server has no WebSocket" (the initial connect / the X-LiveTemplate-WebSocket probe). A transient failure on a reconnect from a client that was already live is a different case, but it takes the same latch.

Expected

A client that was connected over WS and loses the connection keeps retrying the WS, with backoff, and re-syncs when it comes back. The server already pushes a fresh render on connect. HTTP fallback stays an initial-connect decision only.

Acceptance

  • An e2e test, with no reload: connect → go offline → mutate server state → go online → the DOM reflects the mutation within a bounded time.
  • A server that genuinely lacks WS still falls back to HTTP on first connect (existing behaviour unchanged).
  • Retries are bounded or backed off, with no reconnect storm while offline.

Activity

  1. added 2 commits that reference this issue on Nov 4, 2026
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