salmon-lighter-12882
03/30/2026, 11:58 AMtall-airline-16756
03/30/2026, 11:58 AMtall-airline-16756
03/30/2026, 11:59 AMiceServers array passed into your RTCPeerConnection / LiveKit client):
◦ Each entry should be a valid URL string like stun:stun.l.google.com:19302 or turn:turn.example.com:3478?transport=udp.
◦ If you use objects, ensure urls is present and either a string or string array:
▪︎ Valid: { urls: "stun:stun.example.com:3478" } or { urls: ["turn:turn.example.com:3478?transport=udp"], username: "...", credential: "..." }
◦ Remove any stray characters, spaces, or missing scheme (stun/turn). Hostnames must not contain invalid characters.
1. Common mistakes to look for
◦ Leaving out the stun: or turn: scheme.
◦ Including protocol prefixes like https:// instead of `stun:`/`turn:`.
◦ Using an IP with an extra bracket or port formatted incorrectly (e.g., stun:[127.0.0.1]:19302 — brackets are for IPv6).
◦ Passing a bare hostname where an URL is expected (the API expects stun:host:port or stun:host).
1. Quick test steps
◦ Temporarily remove custom ICE servers and let the client use default STUN (if applicable) to verify that the rest of your setup works.
◦ If you must use a TURN server, try a known-good TURN URL (e.g., a public STUN) to see if the error disappears — this isolates the issue to your TURN entry.
If you want, I can review your config
• Please paste the iceServers block (or the snippet where you construct the RTCPeerConnection / pass rtcConfig into LiveKit) — remove any sensitive credentials before sharing.
• Tell me which browser and version you’re testing in, and whether you’re using IPv6 addresses or special hostnames.
If you prefer to run diagnostics first
• Run a Connection Test to check WebSocket, WebRTC, and TURN reachability. The test will confirm whether the problem is malformed ICE URLs versus a network issue.
Next step
• Share the iceServers snippet (redact passwords/keys) and your browser info and I’ll point out the exact line causing the invalid-hostname parsing error and show how to fix it. Sources: Diagnosing Connection Errors with the Connection Test Utility | LiveKit | Firewall Tips for LiveKit Connectivity | LiveKit, with interactive elementssalmon-lighter-12882
03/30/2026, 1:26 PMtall-airline-16756
03/30/2026, 1:26 PMiceServers block you pass to the client or the rtcConfig used to create the PeerConnection (redact credentials). Invalid ICE URLs trigger earlier browser errors and can cascade to engine failures on the server.
◦ Ensure entries use stun: or turn: schemes and correct host/port formats (example: stun:stun.example.com:19302 or turn:turn.example.com:3478?transport=tcp).
1. TURN reachability and network
◦ Confirm TURN is reachable from both client and server networks. If UDP is blocked, ensure you have TURN over TCP/TLS (port 443) available and that firewalls/proxies allow it.
◦ If you suspect a restrictive network, try forcing TURN by setting iceTransportPolicy: 'relay' temporarily.
1. Browser / platform details
◦ Tell me which browser (and version) or which SDK/platform (Node, Android, iOS) you’re using. Some platforms surface different internal errors and require platform-specific checks.
1. Server logs and timestamps
◦ Provide the full server log lines around the error (a few seconds before/after) and the timestamp. That helps identify whether this fails during offer/answer, ICE gathering, or DTLS handshake.
1. Token / project config (brief)
◦ If you recently rotated keys or changed token generation, mention it. Authentication problems usually show as auth errors, but it’s useful to rule out mismatches.
Immediate steps you can try now
1. Temporarily remove custom ICE servers (or replace with a known public STUN) to see if the client can create the PeerConnection without your TURN config.
2. Run the Connection Test utility (checkWebsocket, checkWebRTC, checkTURN). This isolates whether the failure is a malformed URL vs. network blocking.
3. If using TURN, test a TURN server with TCP/TLS on 443 to bypass strict firewalls.
What I need from you to go deeper
• Paste the `iceServers`/rtcConfig snippet you’re using (redact passwords/keys).
• Tell me: browser/SDK & version, server OS, and whether you’re using public TURN or a self-hosted TURN.
• Share a short excerpt of the server log around the error (timestamps help).
If you send those, I’ll examine the config for malformed hostnames or other obvious issues and suggest targeted fixes (or the exact change to make).
Sources: Understanding the STATE_MISMATCH Disconnect Reason | LiveKit | client-sdk-js | livekit/livekit_composite | DeepWiki | Firewall Tips for LiveKit Connectivity | LiveKit | Diagnosing Connection Errors with the Connection Test Utility | LiveKit | Configure ZScaler proxy for LiveKit connections | LiveKit, with interactive elementssalmon-lighter-12882
03/30/2026, 1:42 PMtall-airline-16756
03/30/2026, 1:42 PMconnect()).
2. Your LiveKit server config file (the YAML you used for the VM), specifically the rtc.ice_servers section.
3. Whether you enabled/use coturn in the VM (yes/no) and the coturn config if you customized it.
4. The client platform/browser and version (e.g., Chrome 115 on macOS, or JS SDK version).
5. A short excerpt of the LiveKit server logs around the error (10–20 lines before/after the timestamp).
While you gather that, try these targeted checks you can do right now
• Verify ICE server URL format
◦ Each ICE entry must use stun: or turn:. Examples:
▪︎ stuns/stun: stun:stun.l.google.com:19302
▪︎ turn: turn:turn.example.com:3478?transport=udp or turns:turn.example.com:443?transport=tcp
◦ Do not use https:// or plain hostnames where the RTCPeerConnection expects `stun:`/`turn:` URLs.
◦ If your rtc.ice_servers uses objects, ensure they follow { urls: "turn:host:port", username: "...", credential: "..." }.
• Check for accidental characters or IPv6 formatting
◦ Remove stray brackets or spaces. Example invalid: stun:[127.0.0.1]:19302 — brackets break IPv4.
◦ For IPv6 use correct bracketed format with proper scheme.
• Test with a known-good STUN
◦ Temporarily replace your iceServers with a public STUN (e.g., stun:stun.l.google.com:19302) to confirm the rest of the flow works. If this resolves the browser error, the issue is with your TURN/hostnames.
• Confirm coturn is running and reachable
◦ On the VM, check coturn service status and that the ports you configured (UDP/TCP 3478, and 443 if using TLS) are open.
◦ If UDP is blocked in your environment, ensure you have TURN over TCP/TLS and port 443 allowed.
• Try forcing relay to isolate ICE
◦ In your client rtcConfig, set iceTransportPolicy: 'relay' temporarily to force TURN usage. If the connection changes behavior, it indicates ICE path issues.
What I’ll do once you share the snippets/logs
• Inspect the iceServers and server YAML for malformed hostnames or missing schemes and point out the exact fix.
• Highlight coturn reachability issues if logs show ICE candidates not completing.
• Provide exact config lines to change (server YAML and client rtcConfig) and commands to test coturn reachability from the VM and a client machine.
If you paste the rtc.ice_servers block from your VM config and your client iceServers snippet (redact credentials), plus the server log excerpt and your client/browser version, I’ll pinpoint the problem and give step‑by‑step changes to fix it.
, with interactive elementssalmon-lighter-12882
03/30/2026, 1:45 PMrtc.ice_servers i did not setup it, i only ran the script, and the client side was working with the cloud beforetall-airline-16756
03/30/2026, 1:45 PMrtc.ice_servers is, why it matters for your self‑hosted VM, and the simplest next steps so we can find the malformed hostname that’s causing the WebRTC errors.
What rtc.ice_servers is
• rtc.ice_servers is the server-side configuration (in the LiveKit YAML) that tells LiveKit which STUN/TURN servers to advertise to clients. Those entries become the ICE server URLs passed into the browser/SDK when establishing a WebRTC PeerConnection.
• Each entry must be a properly formatted STUN/TURN URL (for example: stun:stun.l.google.com:19302 or turn:turn.example.com:3478?transport=tcp), or an object with urls, username, and credential.
Why this matters for your self-hosted VM
• When you ran the VM script, the setup may have populated default ICE/TURN entries or left them empty. If a malformed or empty value ended up in the generated config, the client will receive an invalid ICE URL and the browser will throw the parsing error you saw.
• Cloud LiveKit likely provided valid ICE/TURN details automatically, which is why your client worked there but not with the self‑hosted VM.
What to check right now (fast and safe)
1. Locate the server config file
◦ On the VM the LiveKit config usually lives in a YAML file (commonly named livekit.yml or similar in /etc/livekit or the directory created by the script). Open that file and look for an rtc: section and then ice_servers: underneath it.
1. Inspect the rtc.ice_servers block
◦ If you see entries, check they look like:
▪︎ - urls: "stun:stun.l.google.com:19302"
▪︎ - urls: "turn:turn.example.com:3478?transport=tcp", username: "user", credential: "pass"
◦ If you see anything that looks like https://..., an empty string, or a bare hostname without `stun:`/`turn:`, that’s the source of the parsing error.
1. If you can’t find or don’t see rtc.ice_servers
◦ The script may have left it empty or defaulted to something invalid. That means the LiveKit server may be advertising an invalid entry or none at all, causing the client error and the server’s internal WebRTC failure.
If you’re comfortable sharing (redact secrets)
• Paste the rtc.ice_servers block from your VM’s YAML, or paste the section of the YAML around rtc: (you can redact usernames/credentials).
• Tell me the VM OS and where you ran the script (the path to the generated config if you know it).
If you prefer to check manually first, here’s a quick safe test
1. On your client, temporarily try connecting with a client-side override (no secrets needed) that uses a known-good STUN only:
◦ In the client SDK, set iceServers to: [ { urls: "stun:stun.l.google.com:19302" } ]
◦ If connection succeeds (or the browser error disappears), the problem is definitely the server’s ICE entries.
1. On the VM, check the livekit server logs again for any lines referencing ice_servers or ICE candidate failures; that will confirm whether malformed entries are coming from the server.
Next step I can take for you
• If you paste the rtc.ice_servers YAML block (redact passwords/credentials), I’ll point out exactly what’s wrong and give the corrected YAML lines and a small command to reload the LiveKit service., with interactive elementssalmon-lighter-12882
03/30/2026, 1:46 PMtall-airline-16756
03/30/2026, 1:47 PMrtc: block from your VM config and it does not include any ice_servers entries. That likely explains the browser error: the server is advertising either an empty/invalid ICE list or the client is receiving no valid STUN/TURN URLs, which leads to the “Invalid hostname format” and the server-side “engine: internal webrtc failure.”
What to do next (short checklist)
1. Confirm the server is not providing ICE servers
◦ Check for any other LiveKit config files or environment variables the script may have created that reference ice_servers. If none exist, the server currently has no ICE configuration to hand to clients.
1. Quick client-side test to isolate the issue
◦ Temporarily override the client’s ICE servers so the browser receives a known-good STUN:
▪︎ Set the client SDK’s rtcConfig/iceServers to:
▪︎ { urls: "stun:stun.l.google.com:19302" }
▪︎ If the browser error disappears or the connection proceeds further, the problem is definitely the missing/malformed server-side ICE configuration.
1. Add proper rtc.ice_servers to your VM config
◦ Edit your LiveKit YAML and add an ice_servers: block under rtc:. Example minimal entries:
▪︎ For just STUN:
▪︎ rtc:
• tcp_port: 7881
• port_range_start: 50000
• port_range_end: 60000
• use_external_ip: true
• enable_loopback_candidate: false
• ice_servers:
• urls: "stunstun.l.google.com19302"
▪︎ For TURN (coturn) with credentials:
▪︎ ice_servers:
• urls: "turnturn.example.com3478?transport=udp"
username: "TURN_USERNAME" credential: "TURN_PASSWORD"
• urls: "turnsturn.example.com443?transport=tcp"
username: "TURN_USERNAME" credential: "TURN_PASSWORD"
• Important: urls must use `stun:`/`turn:`/`turns:` schemes. Do not use http:// or https:// or bare hostnames.
1. If using coturn bundled with the VM
◦ If you enabled coturn during setup, configure its external hostname and credentials and add the corresponding `turn`/`turns` entries to rtc.ice_servers.
◦ Ensure coturn is running and ports (3478 UDP/TCP, and 443/5349 if you use TLS) are accessible from clients.
1. Restart LiveKit after changing config
◦ After editing the YAML, restart the LiveKit service (or container) so it serves the updated ICE servers to clients.
What I can help with next
• If you paste:
◦ The client-side code where you call connect() (the `iceServers`/rtcConfig section if any), and
◦ The place in your VM config file where you’d like to add ice_servers (you can paste the YAML snippet you have now),
I will:
• Validate the exact YAML syntax and provide the corrected block you can paste in, and
• Give the exact restart command for the VM/container and a short test to verify coturn reachability.
If you prefer, start by testing the client override with the public STUN above and tell me the result — that will quickly confirm the root cause.
, with interactive elements