{"record":{"id":"5126ba5d6d1cf1e9","repo":"thedotmack/claude-mem","slug":"tv-picture-in-picture-failed","errorCode":null,"errorMessage":"[tv] picture-in-picture failed","messagePattern":"\\[tv\\] picture-in-picture failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/ui/tv.html","lineNumber":471,"sourceCode":"    startCanvas();\n    if (!video.srcObject) video.srcObject = els.canvas.captureStream(15);\n    await video.play();\n    if (video.requestPictureInPicture) {\n      await video.requestPictureInPicture();\n    } else if (video.webkitSetPresentationMode) {\n      video.webkitSetPresentationMode('picture-in-picture');\n    }\n  }\n\n  async function togglePiP() {\n    try {\n      if (hasDocumentPiP) {\n        await toggleDocumentPiP();\n        return;\n      }\n      await toggleVideoPiP();\n    } catch (err) {\n      console.warn('[tv] picture-in-picture failed', err);\n    }\n  }\n\n  function toggleFullscreen() {\n    if (document.fullscreenElement) {\n      document.exitFullscreen();\n    } else if (document.documentElement.requestFullscreen) {\n      document.documentElement.requestFullscreen();\n    }\n  }\n\n  let hudTimer = null;\n  function pokeHud() {\n    els.hud.classList.add('show');\n    clearTimeout(hudTimer);\n    hudTimer = setTimeout(() => els.hud.classList.remove('show'), 2500);\n  }\n","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/ui/tv.html#L453-L489","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Trigger the PiP toggle directly from a user click handler to satisfy gesture requirements","Check that the video element exists and is playing before requesting PiP","Fall back to fullscreen or a supported browser (Chrome/Edge) if PiP is unsupported","Catch the rejection reason in the logged err to identify which API rejected"],"exampleFix":"// before\nawait toggleVideoPiP(); // may reject if video not playing\n// after\nconst video = document.querySelector('video');\nif (video && !video.paused) await toggleVideoPiP();\nelse console.warn('[tv] no playing video for PiP');","handlingStrategy":"try-catch","validationCode":"if (!('documentPictureInPicture' in window) && !document.featurePolicy?.allowsFeature('picture-in-picture')) {\n  console.warn('PiP unsupported in this browser');\n}","typeGuard":"function canPiP(video: HTMLVideoElement | null): boolean {\n  return !!video && typeof video.requestPictureInPicture === 'function' && !video.paused;\n}","tryCatchPattern":"try {\n  await toggleVideoPiP();\n} catch (e) {\n  if (e instanceof DOMException && e.name === 'NotAllowedError') {\n    // require user gesture or fall back to fullscreen\n  }\n}","preventionTips":["Only call PiP from direct user-gesture handlers","Check video is loaded and playing first","Provide a fullscreen fallback for unsupported browsers"],"tags":["browser","picture-in-picture","ui"],"backgroundTag":"unsupported-operation","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}