[Bug] Component View: Ghost Breakout Room invitation dialog persists after attendee returns to Main Session

Description

When using the Zoom Meeting SDK Component View (@zoom/meetingsdk/embedded), a phantom “Join Breakout Room” dialog appears after an attendee is moved back to the main session by the host. The dialog persists and cannot be dismissed programmatically.

Flow to reproduce:

  1. Host (Zoom desktop app) assigns an SDK attendee to a breakout room
  2. Attendee is auto-moved to the breakout room (auto-move enabled)
  3. Host assigns the attendee back to the main session
  4. Attendee clicks “Join” on the main session prompt → successfully returns to main session
  5. Bug: The original breakout room invitation dialog (“Join Breakout Room”) reappears with “Join” and “Not Now” buttons, even though the attendee is already in the main session

The dialog is a zoom-MuiDialog-paper element with #confirmation-dialog-title containing “Join Breakout Room”. It is rendered via React portal on document.body by the SDK’s internal React instance.

Browser Console Error

No console error. The dialog simply persists in the DOM after the attendee returns to the main session. The SDK does not unmount/destroy the breakout room invitation modal.

Which Web Meeting SDK version?

@zoom/meetingsdk version 6.2.0 (also reproduced on 3.11.0 and 3.13.2)

Meeting SDK Code Snippets

"use client"
import { useEffect, useRef, useState } from "react"

export default function ZoomMeeting({ sdkKey, meetingNumber, passWord, userName, signature }) {
    const zoomRootRef = useRef(null)
    const clientRef = useRef(null)

    useEffect(() => {
        if (clientRef.current) return
        let client = null

        const initZoom = async () => {
            const ZoomMtgEmbedded = (await import("@zoom/meetingsdk/embedded")).default
            client = ZoomMtgEmbedded.createClient()
            clientRef.current = client

            await client.init({
                zoomAppRoot: zoomRootRef.current,
                language: "en-US",
                patchJsMedia: true,
            })

            await client.join({
                sdkKey, signature, meetingNumber,
                password: passWord, userName,
            })
        }

        initZoom()

        return () => {
            try { client?.leaveMeeting(parseInt(meetingNumber)) } catch {}
            try { ZoomMtgEmbedded.destroyClient() } catch {}
            clientRef.current = null
        }
    }, [])

    return <div ref={zoomRootRef} id="meetingSDKElement" />
}

To Reproduce

  1. Host starts a Zoom meeting from desktop app with breakout rooms enabled and “Automatically move participants” ON
  2. Attendee joins via Meeting SDK Component View (role 0)
  3. Host assigns attendee to a breakout room → attendee auto-moves to the room
  4. Host moves attendee back to main session via “Move to Main Session”
  5. Attendee clicks “Join” on the main session prompt → returns to main session
  6. Ghost dialog appears: “Join Breakout Room - You have been assigned to [Room Name]” with “Join” and “Not Now” buttons

Screenshots

The ghost dialog HTML structure:

<div class="zoom-MuiPaper-root zoom-MuiDialog-paper zoom-MuiDialog-paperWidthMd">
  <h2 id="confirmation-dialog-title">Join Breakout Room</h2>
  <p id="confirmation-dialog-description">You have been assigned to Registration Room 1</p>
  <button>Join</button>
  <button>Not Now</button>
</div>

Troubleshooting Routes

  • Tested on SDK versions 3.11.0, 3.13.2, and 6.2.0 — same behavior on all
  • Tried MutationObserver on document.body to detect and remove the dialog — dialog not caught consistently
  • Tried CSS injection (display: none on .zoom-MuiDialog-root) — did not work
  • Tried auto-clicking “Not Now” button programmatically — not triggered
  • Tried client.leaveBreakoutRoom() on user-updated event — no effect on the dialog
  • Tried client.rename() to force SDK state reset — no effect
  • Tried removing useEffect cleanup (no destroyClient) — dialog still appears
  • No declineBOInvite() or host-ask-unmute event available in embedded SDK types
  • Reviewed Zoom GitHub sample apps — no breakout room handling examples for Component View

Device

  • Device: MacBook Pro
  • OS: macOS 26.2
  • Browser: Chrome
  • Browser Version: 149.0.7827.116 (Official Build) (arm64)

Additional context

  • The host uses the native Zoom desktop app (not SDK)
  • Attendees join via the SDK Component View embedded in a Next.js 14 website
  • The issue appears to be a state desync: when the host moves an attendee back to the main session, the SDK backend retains the breakout room assignment in a “not joined” state. The SDK client then re-reads this stale assignment and re-renders the invitation dialog.
  • On the host’s participant panel, the attendee still shows as “(not joined)” in the breakout room even though they are in the main session — this confirms the backend assignment is not properly cleared.