nextcloud / nextcloud/talk-android

Call fails to join existing call on app launch due to stale roomJoined WebSocket event

Open
#6,044 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage bug
Dominant language
Kotlin
Stars
739
Forks
321
Avg merge
14h 59m
Merged PRs (30d)
151

Description

Steps to reproduce

When launching the app and immediately joining a call that's already in progress, the call sometimes fails to connect with existing participants. The app appears stuck in a "connecting" state. The user must exit the call (and sometimes the channel) and re-enter multiple times before it works.

  1. Have an active call in progress on another device
  2. Open the Android app fresh (cold start or returning after being away)
  3. Tap to join the existing call
  4. Call appears to connect but never shows other participants — stuck in connecting state
Expected behaviour

The app should join the existing call and connect to all current participants.

Actual behaviour

Call fails to join and gets stuck in 'ringing'

Device brand and model

Samsung Galaxy S23

Android version

16

Nextcloud Talk app version

Master

Nextcloud server version

33

Talk version

23

Custom Signaling server configured

Yes (specify version in Additional Information)

Custom TURN server configured

Yes

Custom STUN server configured

Yes

Android logs

00:15:03.899 onMessageEvent 'hello'
00:15:04.206 onMessageEvent 'roomJoined' currentCallStatus=CONNECTING ← fires BEFORE joinRoomAndCall!
00:15:04.652 hasMCU is true
00:15:04.652 joinRoomAndCall ← too late, stale roomJoined already consumed
The roomJoined event at 00:15:04.206 is stale — it was enqueued before joinRoomAndCall() was called at 00:15:04.652.

Server log

Additional information

Root Cause

The flow on app launch is:

  1. CallActivity.onCreate() → CONNECTING state
  2. WebSocket was already connected from a previous session (or ChatActivity had it open)
  3. Server sends hello event → triggers initiateCall() → fetchSignalingSettings() → ...
  4. Server also sends a stale roomJoined event from the previous WebSocket session
  5. The stale roomJoined fires performCall() before joinRoomAndCall() has been called
  6. Later, joinRoomAndCall() runs and calls WebSocketInstance.joinRoomWithRoomTokenAndSession()
  7. The WebSocket sees it's already in the same room/session and does a local join without sending anything to the server
  8. The server never re-sends the participant list because it believes the client is already in the room
  9. handleCallParticipantsChanged() is never called with existing participants
  10. State stays at JOINED, never transitions to IN_CONVERSATION

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in CallActivity.onCreate() and trace the named flow through initiateCall(), fetchSignalingSettings(), performCall(), and joinRoomAndCall(). Inspect WebSocketInstance.joinRoomWithRoomTokenAndSession() and handleCallParticipantsChanged() alongside the roomJoined event handling. Done means a cold-start join receives the existing participant list and reaches IN_CONVERSATION instead of remaining in CONNECTING or JOINED.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
audio-video-rtc, mobile-dev, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.