Audio/video streams broken after conference.max_users encountered

After joining from prejoin page and getting back a rejection due to mod_muc_max_occupants limits, I’ve notices that audio and video is immediately muted.

What’s more troubling is that if user retries to join (without reloading page and just reclicking join) and succeeds, the user does not see video of other users and vice versa.

  • if user unmutes video on prejoin page before rejoining, user can see own video but not others, and others cannot see the user’s video
  • if user leaves video muted when rejoining, video cannot be unmuted (which makes no difference really since nobody else will see it)

We encountered this on latest stable (2.0.7001) and can repro the issue from a local build using latest lib-jitsi-meet (fa916d4) and jitsi-meet (a6ad592)

@damencho I’m afraid I cannot recall if I missed this when testing your fix for a related issue, or if this was broken after.


Error logs:

  • On init max_user failure (where audio/video gets muted), we see the expected error message:
    [conference.js] <ConferenceConnector._onConferenceFailed>: CONFERENCE FAILED: conference.max_users

  • If rejoin succeeds, I don’t see anyone else’s video, and nobody sees mine but I do have a presence in the room. The follow errors are seen on join:

    UnhandledError: Rejecting session-initiate from non-focus
    [JitsiMeetJS.js] <Object.getGlobalOnErrorHandler>:  UnhandledError: Rejecting session-initiate from 
     non-focus. Script: null Line: null Column: null StackTrace:  Error: Rejecting session-initiate from non-focus.
     at jd._rejectIncomingCall (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:582123)
     at jd.onIncomingCall (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:580360)
     at r.emit (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:102447)
     at eo.onJingle (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:360795)
     at P.Handler.run (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:639338)
     at https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:647776
     at Object.forEachChild (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:631006)
     at P.Connection._dataRecv (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:647625)
     at O.Websocket._onMessage (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:676855)
    
    UnhandledError: attempt to initiate on session 2qcra0vud9f9a in state ended
     [JitsiMeetJS.js] <Object.getGlobalOnErrorHandler>:  UnhandledError: attempt to initiate on session 2qcra0vud9f9a in state ended Script: null Line: null Column: null StackTrace:  Error: attempt to initiate on session 2qcra0vud9f9a in state ended
     at Qr.initialize (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:325493)
     at jd._acceptJvbIncomingCall (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:580897)
     at jd.onIncomingCall (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:580445)
     at r.emit (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:102447)
     at eo.onJingle (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:360795)
     at P.Handler.run (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:639338)
     at https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:647776
     at Object.forEachChild (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:631006)
     at P.Connection._dataRecv (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:647625)
     at O.Websocket._onMessage (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:676855)
    
  • If I try to unmute video or audio, if fails and I see the following error:

    UnhandledError: The queue has been stopped
    [JitsiMeetJS.js] <Object.getGlobalOnErrorHandler>:  UnhandledError: The queue has been stopped Script: null Line: null Column: null StackTrace:  Error: The queue has been stopped
    at Vr.push (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:324616)
    at https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:351409
    at new Promise (<anonymous>)
    at Qr.replaceTrack (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:351284)
    at jd._doReplaceTrack (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:570499)
    at jd.replaceTrack (https://meet.my.domain/libs/lib-jitsi-meet.min.js?v=5913:2:569840)
    

In the scenario where max_user failure received (and audio/video auto muted):

  • If I unmute video on prejoin page, video appears to be enabled but the following error shows up
    [JitsiMeetJS.js] <Object.getGlobalOnErrorHandler>: UnhandledError: The play() request was interrupted by a new load request. https://goo.gl/LdLk22 Script: null Line: null Column: null StackTrace: undefined
  • If rejoin succeeds, I see my video but not everyone elses’. And they don’t see mine. I see the same “Rejecting session-initiate from non-focus” and “attempt to initiate on session … in state ended” errors.
  • If at this point I try to mute video, my local video is muted as expected but I get error:
    [modules/xmpp/JingleSessionPC.js] JingleSessionPC[session=JVB,initiator=false,sid=agnus4kbd26lt] removeTrackMute failed
  • If if I then enable video, local video works (others still don’t see me and vice verse) and now I get the error:
    [modules/xmpp/JingleSessionPC.js] JingleSessionPC[session=JVB,initiator=false,sid=agnus4kbd26lt] addTrackUnmute failed
1 Like

I guess it’s again a wrong state in jitsi-meet in prejoin page …

With the conference will join event …

Not sure when I will be able to take a look. Maybe create a ticket in jitsi-meet so we don’t forget, but its not a high priority as max users is something that is rarely seen for us … in other words :slight_smile: any help is welcome :slight_smile:

1 Like

Thanks for the report

Raised ticket: Audio/video streams broken after conference.max_users encountered · Issue #11382 · jitsi/jitsi-meet · GitHub

As a quick workaround, is it to possible to listen for reservations/max-occupants errors with IFrame API so we can handle it a little differently?

If not yet available, would you consider a PR to include it?

I’m not sure we want to expose this in the iframe …

I may have a look tomorrow or Monday …

I tried to take a look at this today. I’m yet to work out why all the tracks were removed when max_user error, but I did get somewhere with session failure after rejoin.

In turns out the previous conference object was still lying around and still handling CALL_INCOMING events. However, because it is no longer subscribed to presence, conference.room.members is empty and the isFocus check fails resulting in the session being rejected.

Not sure this is the right way to fix it, but I managed to make things work by making a small change in _createRoom so it first leaves the old conference before creating a new one. Something like this:

_createRoom(localTracks) {
    if (room) { /* if conference previously create, clean up before creating new one */
        room.leave();
    }
    room = connection.initJitsiConference(APP.conference.roomName, this._getConferenceOptions());

With that change, connections are properly established when I rejoin and I can see everyone and vice-versa.

Is this a sensible approach? or am I just working around a side-effect here rather than addressing an underlying issue?

And there’s still the problems with tracks being removed on rejection …

This is what I found. I’m working on a fix.

1 Like

Thanks Damian. Appreciate it.

If it helps, I think I’ve also worked out why the tracks were being removed. CONFERENCE_FAILED action results in previously set ['features/base/conference'].conference state to be undefined and this triggers tracks middleware to destroy all local tracks. It doesn’t differentiate between different CONFERENCE_FAILED types, so tracks are also removed if max_user (and presumably for reservation errors too).

Can you test this: fix: Cleanups JitsiConference on reservation and max user failures. @damencho by damencho · Pull Request #1986 · jitsi/lib-jitsi-meet · GitHub

My previous fix should have been this :slight_smile:

Thanks! I will test in a couple of hours.

That seems to do the trick :+1:

That leaves the issue with removed tracks. Are you looking at that too? or would you prefer I attempt a PR? Although I’m not sure I trust myself to fiddle with the tracks middleware since I may not know the fully impact of a change :sweat:

Hum, what are the steps to repro the thing you say?

This I think solves everything.

Aaa, I see it …

I will take a look.

I think it is only there where you pointed fix: Skips clearing tracks on conference failed. by damencho · Pull Request #11388 · jitsi/jitsi-meet · GitHub, I checked around … , thank you! You reported it and fixed it :slight_smile:
I asked Saul for a review.

Thanks again! Tested that locally and media tracks no longer disappear. :tada:

Now some bad news… did more testing for the conference cleanup fix and found something strange. When rejoining, sometimes it works and sometimes nothing happens and we once again see the previous “A conference with the same name has already been created!” warning :frowning:

If I wait a while before retry (>5s) then the retry usually (always?) works. If I click join again soon after failure, then there is a high chance of getting the “already created” error.

Not the end of the world since this becomes like free debouncing after room max limit reached :smiley: but not ideal that it is not very deterministic.

I’m changing my stance. This might actually be a good thing.

I take that the conference leave procedure takes a short while since there’s a lot to clean up, and the room leave is done at the end, hence the warning if rejoin too soon. I much rather it behave like this and short-circuiting the too-soon retry, rather than risk having new connection set up before old one torn down and we get the conflicts again.

Feel free to close the issue whenever you see fit. I’m a happy bunny :slight_smile:

Once again, many thanks for all the help. I’ve lost count of how many beers I owe you @damencho !

There is a timeout on leaving the room in ChatRoom … I think that can be optimized a bit, and not executed if not joined or something like that … The slowness comes from there.

1 Like