Team Chat and Huddle state surprises
Team Chat (channels, direct messages, reactions, presence) and huddles are built so that a transient backend fault degrades to a calm, recoverable state instead of an error screen. Most “Team Chat is broken” reports are one of those degrades working as designed. This page covers each surprising state, what causes it, and how to tell a passing degrade from a real fault.Team Chat is empty for a moment, then renders fine
The presence surface degrades open by design: when the dependency that answers it is mid-incident, the route returns a successful response with an empty payload instead of an error, and the dashboard renders an empty rail that fills in on the next poll. Three availability classes trigger it:- Transient Postgres unavailability — a brief database blip or rolling restart.
- PgBouncer query timeouts — a connection-pool timeout on the authentication read that runs before the handler.
- Tenant-schema provisioning gaps — a just-created or just-restored organization whose workspace schema is still finishing setup.
GET /api/v1/team-chat/presence— the who’s-online snapshot; degrades to an empty online list.DELETE /api/v1/team-chat/presence— the graceful go-offline on sign-out; degrades to a no-op acknowledgement.POST /api/v1/team-chat/presence/heartbeat— the beat each signed-in seat sends roughly every 25 seconds; degrades to a no-op acknowledgement.
Messages appear for me but not for one teammate
The member roster, the who’s-online snapshot, and the message list are independent reads served by different backends, and they do not fail together. A stale presence snapshot can render fine while a newer message fetch fails for one seat, and the reverse. The asymmetry to check first is the degrade above: the snapshot is the surface that degrades to empty, so during a degrade one seat sees nobody online while a seat whose snapshot succeeded a moment earlier still shows the old online state. Neither view is wrong at that instant; they are two snapshots of a moving picture taken a moment apart. Presence also expires by design. A seat whose tab closed without a graceful sign-out stops beating and ages out of the online window about a minute after its last heartbeat, while that person’s messages and membership keep reading fine. A teammate who appears offline but answers normally is usually this case, not a fault. What to do: have the affected teammate refresh Team Chat once. If the asymmetry survives a refresh on both seats and persists for more than a few minutes, record what each seat sees and escalate.Reactions remove silently, or a reaction reappears
Reaction state (who reacted with which emoji, and the counts) lives in the realtime cache (Redis) layer, not in the message database, and that layer has a degrade contract:- Reads and adds during a cache outage degrade to an empty summary or a best-effort write.
- A remove during a cache outage acknowledges
204as a no-op instead of claiming404. The platform genuinely cannot tell at that moment whether you had reacted, so it refuses to claim “you had not reacted.”
Huddle shows a live badge with no one in it
A huddle’s live badge is backed by two things that converge over time: the media room’s participant list and a live-huddle marker. When the last participant leaves, the media room reclaims itself a couple of minutes later, and the marker clears either on the leave path or on the next status read: any status poll that finds a marker with no live participants and no start in flight treats the huddle as ended and clears the badge for everyone. When that read-path self-heal has not had a chance to run yet, for example because nobody has polled the channel’s huddle status since it emptied, the badge can briefly linger as live with zero participants, and a join in that window lands in an empty room. Both layers are bounded. The empty room is reclaimed a couple of minutes after the last participant leaves, and even a marker the self-heal never reaches expires on its own within twelve hours, so a phantom badge is always temporary, never permanent. What to do: open the huddle once and leave it. Your join gives the room a real participant, and your leave, as the last one out, runs the cleanup that clears the badge for everyone. A channel refresh alone also runs the read-path self-heal and clears a marker with no live participants. If a channel still shows a live huddle with zero participants an hour after the last real participant left, escalate with the channel id.Joining a huddle returns 409 CONFLICT
Huddle end is recorded asynchronously: the media room closes first and the live-huddle record settles a beat later, in a short flush window. A join that lands inside that window hits a huddle that is on its way out and returns409 CONFLICT instead of half-joining a dying room.
What to do: wait a few seconds and join again. The retry succeeds on
whichever side the race settled: it either joins the huddle that turned
out to stay live, or starts a fresh one. One retry after a pause is safe;
do not loop retries back-to-back.
Team Chat attachment upload fails
Team Chat file sharing uses the same storage plane as Inbox ticket attachments, so a503 ATTACHMENT_STORAGE_UNAVAILABLE on a Team Chat
upload is the same fault as on a ticket: a storage-backend fault that fired
after every validation gate passed, never a problem with your file.
What to do: follow
Ticket attachment storage unavailable:
re-upload the same file with backoff, and if the same file keeps failing,
escalate with the response’s meta.request_id and the file’s checksum.
Escalate
When a state does not clear on refresh and outlives the windows above, open a support ticket with:- a HAR trace of the Team Chat view reproducing the symptom, captured on the affected seat’s browser;
- the route URL of the surface that showed it (the channel or DM you had open);
- the message id, huddle channel id, or message id plus emoji the symptom is about, where one is visible;
- the affected seat and organization, and the time window with timezone.
meta.request_id from each failed response; it pins the exact
attempt in the platform log.
What NOT to do
- Do not advise log-out / log-in. Presence is keyed off the workspace session’s heartbeats and is independent of SSO session state; signing out and back in rebuilds nothing on the server side. Recovery comes from the next poll, not from a fresh session.
- Do not advise clearing localStorage or browser storage. Team Chat drafts are stored server-side, and no client-side cache feeds the who’s-online rail or the huddle badge, so clearing storage fixes none of the states on this page.
- Do not delete and recreate the channel or DM. The states above are presence- and cache-layer state; the messages, roster, and membership underneath them are intact.
- Do not disable huddles or reactions for the organization. A degrade is a transient backend fault handling itself by design; switching a feature off hides a retryable gap behind a configuration change.
See also
- Team Chat guide — the operator guide for channels, direct messages, and huddles.
- Team Chat concept — the data model behind channels, DMs, and huddles.
- Ticket attachment storage unavailable — the shared attachment storage runbook referenced above.
- Error Code Reference — the envelope shape that
carries the
request_idyou escalate with.