WebRTC Softphone Handoff Failing with SDP_NEGOTIATION_ERROR in Architect IVR

Mapping the CXone Digital Agent web config over to the Genesys Cloud softphone settings, and the media path keeps choking during the Architect IVR handoff. The genesys-cloud-webphone-sdk v2.4.1 runs in a US-East-1 BYOC tenant. CXone just used a static webrtc_session_timeout of 45 seconds, but GC’s media_server_region routing seems to be dropping the STUN/TURN candidates before the call bridges.

Console throws SDP_NEGOTIATION_ERROR: ICE_CANDIDATE_FAILURE right when the Architect flow hits the Transfer to Queue block. The SDP payload shows the a=candidate lines getting stripped by the edge load balancer. In CXone, you’d just toggle the force_stun_relay flag in the studio routing script. GC doesn’t have that exact switch. Config pushes the iceTransportPolicy to relay in the SDK init, but the browser still falls back to host candidates. Honestly, it’s doing jack all to fix the relay path.

Any thoughts on how the Media Server region selection interacts with the softphone’s ICE gathering? Pointing everything to us-east-1 but the TURN allocation endpoint keeps timing out after 8 seconds. Is there a specific Architect Set Interaction Attribute step that needs to override the default webrtc_media_policy? Also, should the cti_integration token refresh before the play_prompt block runs?

Network traces show the WebSocket stays open, but the actual RTP stream never negotiates. The CXone fallback just re-ran the STUN discovery on port 3478. GC’s softphone seems to expect the candidates to arrive within the first 300ms of the createOffer handshake. Logs are attached below.
{
“error”: “SDP_NEGOTIATION_ERROR”,
“code”: “ICE_CANDIDATE_FAILURE”,
“sdk_version”: “2.4.1”,
“flow_id”: “architect_ivr_handoff_v3”,
“media_region”: “us-east-1”
}

You’re hitting the ICE candidate timeout because auto-detection lags on BYOC trunks. Force the media server override.

  1. Drop this into your SDK init.
  2. Restart the softphone to flush the STUN cache.
genesysCloudWebPhone.init({
 mediaServerRegion: "us-east-1",
 iceTransportPolicy: "all"
})

Don’t drop the timeout under 30 seconds or the browser kills the handshake. The backend just needs that explicit flag.

The suggestion above nailed it. It’s the ICE timeout on the BYOC edge.

  • Force mediaServerRegion: "us-east-1" in the SDK init.
  • Set iceTransportPolicy: "all" to bypass the proxy filter.
  • Verify the handshake via /api/v2/interaction/webphone/calls.

Screenshot of the clean SDP exchange attached.

{
 "media_server_region": "us-east-1",
 "ice_transport_policy": "all",
 "stun_turn_override": true
}

The usual snag comes from leaving the MEDIA SERVER REGION unset inside the ARCHITECT FLOWS. When the SDK defaults to auto-detect, the BYOC trunk drops the ICE candidates before the handshake completes. Forcing the override locks the media path to the correct edge node.

You’ll also want to verify the TURN RELAY SETTINGS in the tenant config. Proxy filters catch UDP packets if the FIREWALL RULES drift. Happens more than expected. Check the interaction logs via the API to confirm the SDP exchange clears without timeouts. Adjust the ARCHITECT FLOW routing to match the fixed media path. Leave the timeout at forty seconds. The bridge will hold.