{"record":{"id":"83530e11be927fc3","repo":"TanStack/query","slug":"failed-to-open-popup-please-allow-popups-for-this","errorCode":null,"errorMessage":"Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode.","messagePattern":"Failed to open popup\\. Please allow popups for this site to view the devtools in picture-in-picture mode\\.","errorType":"exception","errorClass":"PipOpenError","httpStatus":null,"severity":"warning","filePath":"packages/query-devtools/src/contexts/PiPContext.tsx","lineNumber":63,"sourceCode":"      setPipWindow(null)\n    }\n  }\n\n  // Open new pipWindow\n  const requestPipWindow = (width: number, height: number) => {\n    // We don't want to allow multiple requests.\n    if (pipWindow() != null) {\n      return\n    }\n\n    const pip = window.open(\n      '',\n      'TSQD-Devtools-Panel',\n      `width=${width},height=${height},popup`,\n    )\n\n    if (!pip) {\n      throw new PipOpenError(\n        'Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode.',\n      )\n    }\n\n    // Remove existing styles\n    pip.document.head.innerHTML = ''\n    // Remove existing body\n    pip.document.body.innerHTML = ''\n    // Clear Delegated Events\n    clearDelegatedEvents(pip.document)\n\n    pip.document.title = 'TanStack Query Devtools'\n    pip.document.body.style.margin = '0'\n\n    // Detect when window is closed by user\n    pip.addEventListener('pagehide', () => {\n      props.setLocalStore('pip_open', 'false')\n      setPipWindow(null)","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/TanStack/query/blob/159982c80b844487054155c38ffc760fe4208daf/packages/query-devtools/src/contexts/PiPContext.tsx#L45-L81","documentation":"Thrown as `PipOpenError` from the devtools `PiPProvider` when `window.open(..., 'popup')` returns `null` — i.e. the browser blocked the popup. The devtools picture-in-picture mode is implemented via a real popup window (a fallback before the native Document Picture-in-Picture API), so it depends on the user granting popup permission for the origin. The provider catches this specific error in its `createEffect` and downgrades gracefully (logs the message, resets `pip_open`/`open` flags), but if you call `requestPipWindow` directly it propagates to you.","triggerScenarios":"User clicks the PiP toggle while the browser blocks popups for the site; popup blocker extension active; `window.open` called outside a user-gesture transient activation (e.g. programmatically on mount, or in a `setTimeout`); embedded in an iframe without `allow-popups` in the sandbox attribute; headless / test environment where `window.open` is unavailable.","commonSituations":"Default Chrome/Edge blocking popups on an unfamiliar origin; embedded devtools in a sandboxed iframe (Storybook, CodeSandbox, StackBlitz); CI / end-to-end test runs (Playwright, Puppeteer) where popups are blocked; calling `requestPipWindow` from a non-interactive context.","solutions":["Tell the user to allow popups for the site (browser site settings -> Pop-ups and redirects -> Allow), then click the PiP toggle again.","Ensure `requestPipWindow` is only invoked from a user-gesture handler (click/keydown), not from an effect or timer.","If embedding in an iframe, add `allow=\"popups\"` (and ideally `allow=\"popups; picture-in-picture\"`) to the iframe element.","In tests, grant the popup permission in the browser context, e.g. Playwright `context.grantPermissions(['popup'])` or launch with `--disable-popup-blocking`."],"exampleFix":"// before - iframe blocks the devtools popup\n<iframe src=\"/devtools\" sandbox=\"allow-scripts\"></iframe>\n\n// after - allow popups in the sandbox\n<iframe src=\"/devtools\" sandbox=\"allow-scripts allow-popups\"></iframe>","handlingStrategy":"try-catch","validationCode":"// Check before requesting the PiP popup\nconst canOpenPopup = () => {\n  try {\n    const w = window.open('', '__popup_test__', 'width=1,height=1')\n    if (w) { w.close(); return true }\n    return false\n  } catch {\n    return false\n  }\n}\n// Note: probing has side effects and may itself be blocked; prefer feature-detecting on user gesture.","typeGuard":"// Feature-detect popup support (best effort)\nconst supportsPopups = () =>\n  typeof window !== 'undefined' && typeof window.open === 'function'","tryCatchPattern":"try {\n  requestPipWindow(width, height)\n} catch (e) {\n  if (e.message.startsWith('Failed to open popup')) {\n    // inform the user to allow popups, do not crash\n    setShowPipBlockedMessage(true)\n  } else {\n    throw e\n  }\n}","preventionTips":["Only trigger PiP from a user-gesture handler (click/keydown), never from an effect or setTimeout.","If running in an iframe, add allow=\"popups; picture-in-picture\" to the iframe sandbox.","In E2E tests, launch the browser with --disable-popup-blocking or grant the popup permission.","Surface a friendly UI fallback (e.g. 'Please allow popups') when the error fires."],"tags":["devtools","pip","popup","browser","permissions"],"backgroundTag":null,"analyzedSha":"159982c80b844487054155c38ffc760fe4208daf","analyzedAt":"2026-08-12T16:21:52.822Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}