text chat worked totally fine but voice calls just sat on "connecting" forever spent way too long chasing the wrong things before finding the actual cause so im writing this up in case it saves someone the headache
TLDR: voice is livekit based now and the voice server has both ipv6 and ipv4 addresses. on my network the ipv6 side is just dead (connection refused, or reset mid handshake) while ipv4 works perfectly. the app tries ipv6 first and never falls back to ipv4 so voice hangs forever. text chat kept working the whole time because the chat socket is ipv4 only, which is why it never even looked like a network issue posting the whole thing because the fix is buried in a wall of diagnosis, skip to 'the fix that actually worked for me' if you just want the flag
there were a bunch of red herrings and i fell for basically all of them:
- the "default device" audio fix from another thread, tried it, did nothing for me. might work for you though
- post quantum key agreement / clienthello size stuff. i actually replayed the exact clienthello over raw sockets and it worked fine over ipv4, so only the address family mattered. red herring
- my vpn/proxy tunnel. fine, ipv4 worked directly. red herring
- app version. v1.5.4 behaves the same as the older ones, updating does not help
how to check if this is your problem
first get your voice nodes hostname, stoat publishes it in the settings api:
curl -s https://api.stoat.chat/ | grep -o 'wss://[^"]*livekit[^"]*'
mine (october 2026) was livekit.hel1.voice.stoat.chat, yours might be different
then test both families:
dig +short A livekit.hel1.voice.stoat.chat
dig +short AAAA livekit.hel1.voice.stoat.chat
curl -4 -sv --max-time 10 https://livekit.hel1.voice.stoat.chat/ 2>&1 | tail -5
curl -6 -sv --max-time 10 https://livekit.hel1.voice.stoat.chat/ 2>&1 | tail -5
if the -4 one does a tls handshake fine and the -6 one gets refused or instantly reset, congrats, this is your issue
if you want actual proof instead of guessing, run the app with a net log:
flatpak run chat.stoat.StoatDesktop --log-net-log=/tmp/netlog.json --net-log-capture-mode=IncludeSocketBytes
quit the app after (it only writes the file when it exits) and search it for the livekit host. a dead ipv6 attempt shows up as net_error -101 / os_error 104 on an ipv6 address with no ipv4 retry after it. seeing that in the log is the thing that finally made it click for me
the fix that actually worked for me
didn't touch the app itself, just copied the flatpaks desktop file into my user applications dir and added one chromium flag to the Exec line:
cp /var/lib/flatpak/exports/share/applications/chat.stoat.StoatDesktop.desktop ~/.local/share/applications/
then at the end of the Exec line (keep the existing flatpak run part):
--host-resolver-rules="MAP livekit.hel1.voice.stoat.chat 157.180.45.15"
this pins the voice host straight to the ipv4 address so the app never wastes its one attempt on the broken ipv6 route. voice joined on the first try after that. checked with ss -tnp | grep 157.180.45.15 and there was a proper estab connection
two catches though. the ip is current as of october 2026, if stoat ever moves the node you have to re-run the curl and update the MAP rule. also the override only applies when you launch from the desktop entry (menu, gtk-launch), typing flatpak run yourself skips it
while im here, two other linux things people keep running into: turning your webcam on inside a voice call can disconnect you (known upstream bug, still open), and screen share is capped at 720p30
honestly the real bug is that the client never falls back to ipv4 after an ipv6 socket fails, worth filing that with the for-desktop repo. the net log evidence above is enough for a decent report if you want to do it