Skip to main content

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:
  1. Ask the visitor to start co-browsing from the chat widget — joining is only possible after the visitor initiates.
  2. 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_GRANTED after a successful join, the visitor joined observe-only — a consent ceiling, not a stuck session.
  3. If the visitor ended the session (or either side ended it), the visitor must re-initiate from the widget — an ended session can never be joined again.
Check the join body first-hand: a malformed 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 an X-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:
  1. Relax the frame policy on the page being embedded — remove X-Frame-Options, or add your origin to the CSP frame-ancestors directive so the site is embeddable where the session runs.
  2. Serve the viewer directly (no wrapper iframe) when the customer’s own site policy cannot change.
  3. 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 returned active, then nothing moves. Remedy ladder:
  1. 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.
  2. Treat the reconnect as routine, not as an error — a token good for 30 minutes is safe to re-mint, and started_at is not reset on re-join.
  3. 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}/control can return 502 COBROWSE_CONTROL_FAILED when 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).
Remedy ladder:
  1. Trim the control packet — shorten the selector and the value so the serialized body fits well under 1 MB.
  2. Paginate or trim large custom-tool response bodies at the executor instead of returning one unbounded payload.
  3. Note that 502 COBROWSE_CONTROL_FAILED is a distinct code from CUSTOM_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