{"record":{"id":"3619c2df752d1e14","repo":"jitsi/jitsi-meet","slug":"window-management-unavailable","errorCode":"window-management-unavailable","errorMessage":"Window Management API unavailable; cannot place second-screen window \"${id}\"","messagePattern":"Window Management API unavailable; cannot place second-screen window \"(.+?)\"","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"react/features/multi-screen/functions.web.ts","lineNumber":1132,"sourceCode":"        handle: ISecondScreenHandle,\n        pending: Promise<ScreenDetails>,\n        screenId?: number): Promise<void> {\n    let error: unknown;\n    const resolved = await pending.then(details => details, e => {\n        error = e;\n\n        return undefined;\n    });\n\n    if (getHandle(store.getState(), id) !== handle || handle.win.closed) {\n        logger.debug(`Dropping the window-management answer for second screen \"${id}\": `\n            + 'it no longer owns that window');\n\n        return;\n    }\n\n    if (!resolved) {\n        logger.warn(`Window Management API unavailable; cannot place second-screen window \"${id}\"`, error);\n        failSecondScreenOpen(store, id, 'window-management-unavailable', handle.win);\n\n        return;\n    }\n\n    placeSecondScreenWindow(handle.win, resolved, screenId);\n    await fullscreenSecondScreen(handle.win, id);\n}\n\n/**\n * Opens and sets up the window for an id, having established that it has no live\n * window and no other open in flight (see {@link openOrUpdateSecondScreen}).\n *\n * @param {IStore} store - The redux store.\n * @param {string} id - The window id.\n * @param {number} screenId - Optional target screen index.\n * @returns {Promise<void>}\n */","sourceCodeStart":1114,"sourceCodeEnd":1150,"githubUrl":"https://github.com/jitsi/jitsi-meet/blob/98de6219cc7ddbe07ace9fde045aff90a242ba01/react/features/multi-screen/functions.web.ts#L1114-L1150","documentation":"This warning fires in the multi-screen (second screen) flow when the browser's Window Management API cannot resolve a target screen for the newly opened second-screen window. The code first checks whether the window handle is still owned (e.g., not closed by the user) and, if it is gone, silently returns; only when the handle exists but screen resolution failed does it log this and abort via failSecondScreenOpen. It is a graceful degradation path, not a crash.","triggerScenarios":"Calling openSecondScreenWindow / placeSecondScreenWhenPermitted on a browser without the Window Management API (window.getScreenDetails / getCurrentScreens not available or not permitted), denying the 'window-management' permission prompt, running over http:// (API requires a secure context), or the API being disabled by enterprise policy. The placement promise rejects or resolves undefined while the popup handle is still alive.","commonSituations":"Firefox/Safari (no Window Management support), Chrome without the window-management permission granted, iframe embeds without allow=\"window-management\" in the iframe allow attribute, http:// dev environments, headless/older Chrome versions.","solutions":["Ensure the app runs on https:// and in a browser that implements the Window Management API (Chrome/Edge 100+).","Request the window-management permission before opening the second screen (navigator.userRequiresPermission / getScreenDetails() must be awaited and granted); for iframe embeds add allow=\"window-management\" to the iframe element.","Upgrade to a recent Chrome/Edge version; verify the API is not blocked by enterprise policy (WindowManagementAllowed policy).","If support cannot be guaranteed, detect API availability up front and hide/disable the second-screen UI instead of attempting placement."],"exampleFix":"// before\nopenSecondScreenWindow(store, id, screenId); // warns: window-management-unavailable\n\n// after\nif (typeof window !== 'undefined' && 'getScreenDetails' in window) {\n    openSecondScreenWindow(store, id, screenId);\n} else {\n    logger.warn('Window Management API not available; second screen disabled');\n}","handlingStrategy":"validation","validationCode":"const canPlaceWindows = typeof window !== 'undefined'\n    && 'getScreenDetails' in window\n    && window.isSecureContext;","typeGuard":"const hasWindowManagement = (w: Window & { getScreenDetails?: unknown }): w is Window & { getScreenDetails: () => Promise<ScreenDetails> } =>\n    typeof w.getScreenDetails === 'function' && window.isSecureContext;","tryCatchPattern":"try { await placeSecondScreen(...); } catch (e) { /* fall back to opening in a regular window */ failSecondScreenOpen(store, id, 'window-management-unavailable'); }","preventionTips":["Feature-detect getScreenDetails before showing second-screen UI.","Request and await the window-management permission early in the flow.","For iframe embeds, include allow=\"window-management\" on the iframe.","Always run over https:// (secure context is required)."],"tags":["multi-screen","window-management","browser-api","permissions"],"backgroundTag":"browser-api-unavailable","analyzedSha":"98de6219cc7ddbe07ace9fde045aff90a242ba01","analyzedAt":"2026-08-28T15:15:59.482Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}