Troubleshooting: co-browse session stuck
A co-browse session moves through a short lifecycle: the visitor starts it from the chat widget, an agent joins the data-channel room, and guided control packets flow once the visitor granted control. A session that is “stuck” broke at one of those steps, and the error your integration saw —COBROWSE_NOT_ACTIVE, a browser frame-policy block, a dropped socket, or a
CUSTOM_TOOL_RESPONSE_TOO_LARGE (502) — names the step.
This page works one stuck co-browse down to a cause. The full join, end,
privacy, and control workflow is on the Co-browse API
reference; this page is the remedy ladder for each failure class.
Symptom map
COBROWSE_NOT_ACTIVE on join — the session never started
POST /api/v1/cobrowse/{conversationId}/join returns
404 COBROWSE_NOT_ACTIVE when the conversation has no live, joinable
session: the visitor has not started co-browsing from the chat widget, or
the previous session already ended. POST /api/v1/cobrowse/{conversationId}/control returns the same code when no
live session exists.
Remedy ladder:
- Ask the visitor to start co-browsing from the chat widget — joining is only possible after the visitor initiates.
- Re-issue the join request once the session exists; on an already-active
session the join endpoint is idempotent, so retrying is safe. If control
packets come back with
403 COBROWSE_CONTROL_NOT_GRANTEDafter a successful join, the visitor joined observe-only — a consent ceiling, not a stuck session. - If the visitor ended the session (or either side ended it), the visitor
must re-initiate from the widget — an
endedsession can never be joined again.
conversationId or body is
refused with 422 VALIDATION_ERROR before the active-session check runs,
so fix the body before treating the session as missing.
The frame won’t load — CSP / X-Frame-Options blocks embedding
When your operator UI embeds the co-browse viewer and the customer page is embedded in return, either frame can be refused by the browser: the customer site sends anX-Frame-Options: DENY or SAMEORIGIN header, or
its Content-Security-Policy frame-ancestors directive excludes your
origin, and the embedded view never renders.
Remedy ladder:
- Relax the frame policy on the page being embedded — remove
X-Frame-Options, or add your origin to the CSPframe-ancestorsdirective so the site is embeddable where the session runs. - Serve the viewer directly (no wrapper iframe) when the customer’s own site policy cannot change.
- Confirm with the page’s owner which relaxation is acceptable — frame policy sits on the customer’s site, and the choice between it and an unframed viewer is their call.
The session starts, then freezes — an edge PoP dropped the data-channel socket
A session can join successfully and then freeze with no further DOM updates when the closest edge point-of-presence drops the data-channel (WebSocket) socket. Symptom: the join returnedactive, then nothing
moves.
Remedy ladder:
- Reconnect the room with the client SDK — it re-mints the join token by calling the join endpoint again, which is idempotent on an already-active session.
- Treat the reconnect as routine, not as an error — a token good for 30
minutes is safe to re-mint, and
started_atis not reset on re-join. - If reconnects flap constantly, check that an intermediate proxy is not terminating long-lived WebSockets on an idle timeout.
Guided control or a custom-tool dispatch returns 502 — the 1 MB ceiling
Co-browse action requests — a guided-control packet, or a custom tool an agent invokes during the session — travel over the data channel as a dispatch payload. A payload over the 1 MB ceiling is refused with a 502:POST /api/v1/cobrowse/{conversationId}/controlcan return502 COBROWSE_CONTROL_FAILEDwhen the packet could not be delivered.- A custom-tool executor whose response body exceeds the 1 MB cap returns
CUSTOM_TOOL_RESPONSE_TOO_LARGE(502).
- Trim the control packet — shorten the selector and the
valueso the serialized body fits well under 1 MB. - Paginate or trim large custom-tool response bodies at the executor instead of returning one unbounded payload.
- Note that
502 COBROWSE_CONTROL_FAILEDis a distinct code fromCUSTOM_TOOL_RESPONSE_TOO_LARGE; the first covers delivery of control packets into the room, the second covers a custom-tool executor’s response size. Both share the same remedy — a smaller body.
Reading errors from the activity feed
When the HTTP verdict alone doesn’t pin the stage, read the operator activity feed on the conversation.GET /api/v1/conversations/{id}/activity
returns the activity stream — status changes, assignments, and errors
recorded on the thread — which shows where the co-browse attempt stalled.
See the Conversations API for the endpoint
contract. Match what the feed recorded against the symptom classes above:
no joinable session, a frame-policy block, a dropped socket, or an
oversized dispatch payload.
See also
- Co-browse API — the full session, privacy, and control workflow this page diagnoses.
- Conversations API — the activity feed endpoint for reading session errors.
- FAQ: Why did my co-browse session fail to start or leave the customer stuck? — the short-entry version of this page.
- Error codes — the full
COBROWSE_*andCUSTOM_TOOL_RESPONSE_TOO_LARGEcodes this page works from.