Closing or reloading any Lotus tab/window erases your custom status for everyone: the pagehide presence write omits status_msg #339

Closed
opened 2026-10-06 13:01:57 -04:00 by jared · 0 comments
Owner

usePresenceUpdater.ts:164-179 (handlePageHide) sends a keepalive PUT /presence/{user}/status with the body {"presence":"offline"}, without status_msg. Synapse treats a missing status_msg as clearing it (it isn't "unchanged").

Synapse behaviour, checked directly (local Synapse, 11 s between writes because of the 10 s presence limit):

PUT {"presence":"online","status_msg":"Gone fishing"}   → online/Gone fishing
PUT {"presence":"offline"}            (pagehide body)   → unavailable/∅        ← status gone
PUT {"presence":"offline","status_msg":"Gone fishing"}  → unavailable/Gone fishing

In the app: the status was set to "Gone fishing", then a second session of the same user was reloaded.

  • The new page's first GET /presence already returned no status_msg, and its startup write was {"presence":"online"}.
  • The status was gone for everyone (checked from another user's view every 5 s).

Closing the session that set the status does the same: that's why the status in #300's scenario disappeared well before the expiry.

It's intermittent, which makes it hard to report. If the pagehide write lands within 10 s of another presence write it's 429'd and the status survives (in one run a reload kept it). A cold open with no pagehide also keeps it ✔: the heartbeat re-sends the server's status, checked both while online and after Synapse marked the user unavailable.

What triggers it: any pagehide — closing the tab or window, reloading, navigating away, logging in on a new tab and closing the old one, and the desktop app's full quit. With several devices, one closing tab wipes the status the phone set a minute ago.

Fix: include the current status in the pagehide write: { presence: 'offline', status_msg: readStatus() } (and the same for any other bare write). Alternatively drop the pagehide write: Synapse marks you offline ~30 s after the last /sync anyway, and with several devices open the explicit "offline" is wrong for the user as a whole (cf. #282). Once fixed, #300 (expiry only on the setting device) becomes the visible behaviour, so fix both together.


Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny 30e2dbcd, cinny-desktop 8f67ec7, element-call 3b0050e8.

`usePresenceUpdater.ts:164-179` (`handlePageHide`) sends a keepalive `PUT /presence/{user}/status` with the body **`{"presence":"offline"}`**, without `status_msg`. Synapse treats a missing `status_msg` as clearing it (it isn't "unchanged"). **Synapse behaviour, checked directly** (local Synapse, 11 s between writes because of the 10 s presence limit): ``` PUT {"presence":"online","status_msg":"Gone fishing"} → online/Gone fishing PUT {"presence":"offline"} (pagehide body) → unavailable/∅ ← status gone PUT {"presence":"offline","status_msg":"Gone fishing"} → unavailable/Gone fishing ``` **In the app:** the status was set to "Gone fishing", then a second session of the same user was reloaded. - The new page's first `GET /presence` already returned no `status_msg`, and its startup write was `{"presence":"online"}`. - The status was gone for everyone (checked from another user's view every 5 s). Closing the session that set the status does the same: that's why the status in #300's scenario disappeared well before the expiry. It's **intermittent**, which makes it hard to report. If the pagehide write lands within 10 s of another presence write it's 429'd and the status survives (in one run a reload kept it). A cold open with no pagehide also keeps it ✔: the heartbeat re-sends the server's status, checked both while online and after Synapse marked the user unavailable. **What triggers it:** any `pagehide` — closing the tab or window, reloading, navigating away, logging in on a new tab and closing the old one, and the desktop app's full quit. With several devices, one closing tab wipes the status the phone set a minute ago. **Fix:** include the current status in the pagehide write: `{ presence: 'offline', status_msg: readStatus() }` (and the same for any other bare write). Alternatively drop the pagehide write: Synapse marks you offline ~30 s after the last /sync anyway, and with several devices open the explicit "offline" is wrong for the user as a whole (cf. #282). Once fixed, #300 (expiry only on the setting device) becomes the visible behaviour, so fix both together. --- _Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny `30e2dbcd`, cinny-desktop `8f67ec7`, element-call `3b0050e8`._
jared added the bugpriority: mediumarea: settings labels 2026-10-06 13:01:57 -04:00
jared closed this issue 2026-10-11 22:57:26 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#339