jitsi/jitsi-meet · error · Error

WrongSurfaceSelected

Error message

WrongSurfaceSelected

What it means

Thrown when the user, during the getDisplayMedia prompt for local recording with self-recording, picks a surface that is not the current browser tab. Jitsi requires the recording to capture the app's own tab, verified via displaySurface === 'browser' and the Capture Handle API matching handle 'JitsiMeet-<tabId>'. Any other choice (window, monitor, different tab) stops the acquired tracks and throws 'WrongSurfaceSelected'.

Source

Thrown at react/features/recording/components/Recording/LocalRecordingManager.web.ts:224

                    restrictOwnAudio: false,
                    // @ts-ignore
                    suppressLocalAudioPlayback: false,
                },
                // @ts-ignore
                preferCurrentTab: true,
                surfaceSwitching: 'exclude'
            });

            const gdmVideoTrack = gdmStream.getVideoTracks()[0];

            if (supportsCaptureHandle) {
                const isBrowser = gdmVideoTrack.getSettings().displaySurface === 'browser';
                const matchesHandle = (supportsCaptureHandle // @ts-ignore
                    && gdmVideoTrack.getCaptureHandle()?.handle === `JitsiMeet-${tabId}`);

                if (!isBrowser || !matchesHandle) {
                    gdmStream.getTracks().forEach((track: MediaStreamTrack) => track.stop());
                    throw new Error('WrongSurfaceSelected');
                }
            }

            this.initializeAudioMixer();

            const gdmAudioTrack = gdmStream.getAudioTracks()[0];

            if (!gdmAudioTrack) {
                throw new Error('NoAudioTrackFound');
            }

            this.addAudioTrackToLocalRecording(gdmAudioTrack);

            const localAudioTrack = getLocalTrack(tracks, MEDIA_TYPE.AUDIO)?.jitsiTrack?.track;

            if (localAudioTrack) {
                this.addAudioTrackToLocalRecording(localAudioTrack);
            }

View on GitHub (pinned to 98de6219cc)

Solutions

  1. Instruct the user (pre-prompt UI/notification) that they must select 'This Tab' / the browser tab option in the picker
  2. Verify browser support: requires Chromium with Capture Handle API; prefer/require Chrome and ensure the deployment injects the capture handle (JitsiMeet-<tabId>) metadata so getCaptureHandle() matches
  3. Catch the error and restart the flow with a clear message so the user can retry and pick the right surface
  4. If cross-browser support is needed, relax the matchesHandle check only when supportsCaptureHandle is false, relying on displaySurface alone

Example fix

// before
if (!isBrowser || !matchesHandle) {
    gdmStream.getTracks().forEach(t => t.stop());
    throw new Error('WrongSurfaceSelected');
}

// after (guide the user and let them retry)
if (!isBrowser || !matchesHandle) {
    gdmStream.getTracks().forEach(t => t.stop());
    dispatch(showErrorNotification({
        titleKey: 'localRecording.wrongSurface',
        descriptionKey: 'localRecording.selectThisTab'
    }));
    return; // or re-open the picker
}
Defensive patterns

Strategy: validation

Validate before calling

const supports = 'getCaptureHandle' in videoTrack && browser.isChromeBased;
// Before the picker: notify user to pick 'This Tab'
showInfoNotification({ descriptionKey: 'localRecording.selectThisTab' });
await manager.startLocalRecording(); // getDisplayMedia with preferCurrentTab: true

Type guard

const isCorrectSurface = (t: MediaStreamTrack, tabId: string): boolean =>
    t.getSettings().displaySurface === 'browser'
    && (t as any).getCaptureHandle?.()?.handle === `JitsiMeet-${tabId}`;

Try / catch

try {
    await manager.startLocalRecording();
} catch (e: unknown) {
    if (e instanceof Error && e.message === 'WrongSurfaceSelected') {
        showWarning('Please select this browser tab when sharing.');
        // optionally re-run the flow once
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: startLocalRecording with selfRecording enabled calls getDisplayMedia; the user selects 'Window' or 'Entire Screen' instead of the browser tab, or selects a different browser tab whose captureHandle doesn't equal `JitsiMeet-${tabId}`, or the browser doesn't support Capture Handle / doesn't transmit the handle (matchesHandle false).

Common situations: User confusion in the Chrome screen-share dialog; Firefox/Safari lacking capture handle support (supportsCaptureHandle false makes matchesHandle false and the check fail); sites without a capture handle config; tabId mismatch after duplication.

Related errors


AI-assisted analysis of jitsi/jitsi-meet@98de6219cc (2026-08-28). Data as JSON: /api/errors/995087a17c0bddf2. Report an issue: GitHub.