TanStack/query · warning · PipOpenError

Failed to open popup. Please allow popups for this site to v

Error message

Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode.

What it means

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.

Source

Thrown at packages/query-devtools/src/contexts/PiPContext.tsx:63

      setPipWindow(null)
    }
  }

  // Open new pipWindow
  const requestPipWindow = (width: number, height: number) => {
    // We don't want to allow multiple requests.
    if (pipWindow() != null) {
      return
    }

    const pip = window.open(
      '',
      'TSQD-Devtools-Panel',
      `width=${width},height=${height},popup`,
    )

    if (!pip) {
      throw new PipOpenError(
        'Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode.',
      )
    }

    // Remove existing styles
    pip.document.head.innerHTML = ''
    // Remove existing body
    pip.document.body.innerHTML = ''
    // Clear Delegated Events
    clearDelegatedEvents(pip.document)

    pip.document.title = 'TanStack Query Devtools'
    pip.document.body.style.margin = '0'

    // Detect when window is closed by user
    pip.addEventListener('pagehide', () => {
      props.setLocalStore('pip_open', 'false')
      setPipWindow(null)

View on GitHub (pinned to 159982c80b)

Solutions

  1. Tell the user to allow popups for the site (browser site settings -> Pop-ups and redirects -> Allow), then click the PiP toggle again.
  2. Ensure `requestPipWindow` is only invoked from a user-gesture handler (click/keydown), not from an effect or timer.
  3. If embedding in an iframe, add `allow="popups"` (and ideally `allow="popups; picture-in-picture"`) to the iframe element.
  4. In tests, grant the popup permission in the browser context, e.g. Playwright `context.grantPermissions(['popup'])` or launch with `--disable-popup-blocking`.

Example fix

// before - iframe blocks the devtools popup
<iframe src="/devtools" sandbox="allow-scripts"></iframe>

// after - allow popups in the sandbox
<iframe src="/devtools" sandbox="allow-scripts allow-popups"></iframe>
Defensive patterns

Strategy: try-catch

Validate before calling

// Check before requesting the PiP popup
const canOpenPopup = () => {
  try {
    const w = window.open('', '__popup_test__', 'width=1,height=1')
    if (w) { w.close(); return true }
    return false
  } catch {
    return false
  }
}
// Note: probing has side effects and may itself be blocked; prefer feature-detecting on user gesture.

Type guard

// Feature-detect popup support (best effort)
const supportsPopups = () =>
  typeof window !== 'undefined' && typeof window.open === 'function'

Try / catch

try {
  requestPipWindow(width, height)
} catch (e) {
  if (e.message.startsWith('Failed to open popup')) {
    // inform the user to allow popups, do not crash
    setShowPipBlockedMessage(true)
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of TanStack/query@159982c80b (2026-08-12). Data as JSON: /api/errors/83530e11be927fc3. Report an issue: GitHub.