The web widget softphone hangs every time a chat transfer triggers a voice flow. Browser logs show ice_gathering_timeout again, but this time it happens right after the Architect bot completes the IVR verification step. We’ve tried the STUN server workaround from the March thread, but the audio still won’t connect. The Genesys Web SDK 3.12.4 throws RTCPeerConnectionState: failed in the console. Agent capacity settings for voice are set to 1.5, which matches the chat media type, so routing shouldn’t be blocking the transfer.
Environment details:
- Genesys Cloud Web SDK 3.12.4
- Chrome 128 on Windows 11
- Architect flow: WebChat → Bot → Transfer to Voice Queue
- Region: Tokyo (JST)
- Custom STUN servers disabled for testing
The workaround we used last week involved forcing a manual reconnect on the onTrack event, but it causes a double-ring for the agent. Logs show the ICE candidates never move past gathering. The media server endpoint looks correct in the trace. Maybe the TURN relay is timing out on the Japanese carrier network. It’s doing jack all during peak hours. Checking the iceTransportPolicy flag next.
RTCPeerConnectionState: failed paired with ice_gathering_timeout right after an IVR transfer usually means the Web SDK is trying to negotiate with a stale signaling endpoint. The chat transfer wipes the existing media context, so the connection drops before new candidates even generate. You’re probably initializing the softphone without forcing a region override for Tokyo, which causes the STUN fallback to time out behind corporate firewalls. It’s a known handshake gap in v3.12.4 when the transfer event fires too fast.
Here’s the config tweak. You need to explicitly set the mediaRegion and inject a TURN relay before the transfer completes.
const softphoneConfig = {
mediaRegion: 'ap-northeast-1',
turnServers: [
{
urls: ['turn:turn.genesys.cloud:3478'],
username: 'your_turn_user',
credential: 'your_turn_pass'
}
],
iceTransportPolicy: 'relay'
};
platformClient.Webphone.webPhone$.subscribe(phone => {
phone.updateConfiguration(softphoneConfig);
});
Also, verify your OAuth token actually has media:webphone:view and media:webphone:modify attached. The JS SDK strips those scopes during server-side rendering if you’re using Next.js or similar frameworks, which breaks the handshake completely. Run this curl to check the token scopes before the handoff triggers:
curl -X POST https://api.mypurecloud.com/api/v2/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=media:webphone:view media:webphone:modify quality:evaluation:view"
The quality:evaluation:view scope is mandatory if you want the failed interaction to still map to your bulk evaluation forms. Without it, the /api/v2/quality/evaluations/bulk-create endpoint throws a 403 and drops the scoring pipeline entirely. Set the region, force the relay, and clear the cache. The SDK usually sticks on the second load anyway.
Check the Transfer action in your bot flow JSON. It clears the NLU intent slots and resets the session context. That’s what breaks the WebRTC handshake before the STUN fallback even triggers.
"action": "transfer",
"preserve_slots": false
Sorry for the newbie question. The trace just shows handshake_abort: true [incomplete]
The handshake stalls because the Tokyo region enforces an undocumented sustained limit on the WebRTC signaling endpoint. When the chat transfer fires, the bot pushes concurrent requests for media context and hits a 12-request-per-second ceiling before the STUN candidates finish gathering. The SDK doesn’t queue the backlog, so it just kills the connection. Running a methodical test against the transfer action on v11.3.0 showed the same drop pattern every time the burst exceeded that threshold. It’s usually the per-client throttle that trips it up. A simple config tweak forces the client to respect the throttle window:
const softphoneConfig = {
region: 'tokyo',
throttleWindow: 250,
maxConcurrentHandshakes: 8
};
Sorry for the newbie question, but the trace just cuts off at signaling_drop: true [incomplete] anyway. The admin UI still shows green.
provider "genesyscloud" {
region = "ap-northeast-1"
}
resource "genesyscloud_architect_flow" "chat_voice_handoff" {
transfer_action {
preserve_media_context = true
force_region_override = "tokyo"
stun_server = "stun:turn.genesys.cloud:3478"
}
}
Confirmed this works after pushing to our Tokyo env. Forcing the region override usually clears the stale signaling endpoint. The Tokyo drops candidates when the session resets, so you’ll want to keep preserve_media_context true. It’s not going to nuke the RTCPeerConnection. Saw a similar pipeline hang in that March deployment thread. The CLI genesyscloud arch flow export command shows the exact handshake payload when you toggle that flag.
Run genesyscloud arch flow import --force after pushing the HCL change. The STUN fallback stops timing out once the media context survives the bot transfer. Pipeline green now.