thedotmack/claude-mem · warning

[tv] picture-in-picture failed

Error message

[tv] picture-in-picture failed

What it means

The TV UI's picture-in-picture toggle awaits either the Document Picture-in-Picture API or the video-element PiP API; if either throws (unsupported API, user gesture requirement, or browser refusal) it logs this warning and silently continues.

Solutions

  1. Trigger the PiP toggle directly from a user click handler to satisfy gesture requirements
  2. Check that the video element exists and is playing before requesting PiP
  3. Fall back to fullscreen or a supported browser (Chrome/Edge) if PiP is unsupported
  4. Catch the rejection reason in the logged err to identify which API rejected

Example fix

// before
await toggleVideoPiP(); // may reject if video not playing
// after
const video = document.querySelector('video');
if (video && !video.paused) await toggleVideoPiP();
else console.warn('[tv] no playing video for PiP');
Defensive patterns

Strategy: try-catch

Validate before calling

if (!('documentPictureInPicture' in window) && !document.featurePolicy?.allowsFeature('picture-in-picture')) {
  console.warn('PiP unsupported in this browser');
}

Type guard

function canPiP(video: HTMLVideoElement | null): boolean {
  return !!video && typeof video.requestPictureInPicture === 'function' && !video.paused;
}

Try / catch

try {
  await toggleVideoPiP();
} catch (e) {
  if (e instanceof DOMException && e.name === 'NotAllowedError') {
    // require user gesture or fall back to fullscreen
  }
}

Prevention

When it happens

Trigger: toggleDocumentPiP() or toggleVideoPiP() rejects: documentPictureInPicture not available despite hasDocumentPiP check passing oddly, requestPictureInImage/PiP rejected because no video is playing, or the call was not triggered by a user gesture.

Common situations: Browser blocks PiP without a fresh user gesture; video element not loaded or paused; browser lacks PiP support (Firefox on some platforms); PiP window already open in an invalid state.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/5126ba5d6d1cf1e9. Report an issue: GitHub.

Appendix: source

Thrown at src/ui/tv.html:471

    startCanvas();
    if (!video.srcObject) video.srcObject = els.canvas.captureStream(15);
    await video.play();
    if (video.requestPictureInPicture) {
      await video.requestPictureInPicture();
    } else if (video.webkitSetPresentationMode) {
      video.webkitSetPresentationMode('picture-in-picture');
    }
  }

  async function togglePiP() {
    try {
      if (hasDocumentPiP) {
        await toggleDocumentPiP();
        return;
      }
      await toggleVideoPiP();
    } catch (err) {
      console.warn('[tv] picture-in-picture failed', err);
    }
  }

  function toggleFullscreen() {
    if (document.fullscreenElement) {
      document.exitFullscreen();
    } else if (document.documentElement.requestFullscreen) {
      document.documentElement.requestFullscreen();
    }
  }

  let hudTimer = null;
  function pokeHud() {
    els.hud.classList.add('show');
    clearTimeout(hudTimer);
    hudTimer = setTimeout(() => els.hud.classList.remove('show'), 2500);
  }

View on GitHub (pinned to d8bc9755e7)