{"record":{"id":"d4ba91797a8d5ccb","repo":"different-ai/openwork","slug":"clipboard-is-not-available-in-this-browser","errorCode":null,"errorMessage":"Clipboard is not available in this browser.","messagePattern":"Clipboard is not available in this browser\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"ee/apps/den-web/app/(den)/_components/workspace-claim-screen.tsx","lineNumber":243,"sourceCode":"    setHandoffAttempted(true);\n\n    try {\n      window.location.assign(await createDesktopHandoff());\n    } catch (error) {\n      setHandoffError(error instanceof Error ? error.message : \"Could not open OpenWork.\");\n    } finally {\n      setHandoffBusy(false);\n    }\n  }\n\n  async function handleCopyOpenWorkLink() {\n    setCopyBusy(true);\n    setLinkCopied(false);\n    setHandoffError(null);\n\n    try {\n      if (!navigator.clipboard) {\n        throw new Error(\"Clipboard is not available in this browser.\");\n      }\n\n      const openworkUrl = await createDesktopHandoff();\n      await navigator.clipboard.writeText(openworkUrl);\n      setLinkCopied(true);\n      window.setTimeout(() => setLinkCopied(false), 1800);\n    } catch (error) {\n      setHandoffError(error instanceof Error ? error.message : \"Could not copy the OpenWork link.\");\n    } finally {\n      setCopyBusy(false);\n    }\n  }\n\n  function continueInBrowser() {\n    router.replace(getOrgDashboardRoute(claimedOrg?.organizationSlug ?? null));\n  }\n\n  if (!token) {","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/_components/workspace-claim-screen.tsx#L225-L261","documentation":"workspace-claim-screen.tsx throws this before attempting the handoff request when `navigator.clipboard` is undefined. The Clipboard API is only available in secure contexts (HTTPS or localhost) and in some browsers requires focus/permission.","triggerScenarios":"User clicks 'Copy OpenWork link' while the page is served over plain HTTP, inside a non-secure iframe, or in a browser/webview that does not expose navigator.clipboard (older browsers, some in-app webviews).","commonSituations":"Den web accessed via http:// on a LAN IP; embedded in an iframe without clipboard permission policy; iOS in-app browser or old Chrome/Firefox versions lacking the async Clipboard API.","solutions":["Serve the app over HTTPS (or localhost) so the Clipboard API is exposed","Add a clipboard-write permission policy if embedded in an iframe (`allow=\"clipboard-write\"`)","Fall back to `document.execCommand(\"copy\")` with a hidden textarea for non-secure contexts","Show the link as selectable text so the user can copy it manually"],"exampleFix":"// before\nif (!navigator.clipboard) {\n  throw new Error(\"Clipboard is not available in this browser.\");\n}\n// after\nif (!navigator.clipboard) {\n  await legacyCopyText(openworkUrl);\n  return;\n}","handlingStrategy":"fallback","validationCode":"if (!window.isSecureContext || !navigator.clipboard) {\n  showFallbackCopyUI(linkText); // manual-select + execCommand path\n  return;\n}","typeGuard":"function clipboardAvailable(nav: Navigator): nav is Navigator & { clipboard: Clipboard } {\n  return typeof nav.clipboard !== \"undefined\";\n}","tryCatchPattern":"try {\n  await navigator.clipboard.writeText(url);\n} catch (err) {\n  legacyCopyViaExecCommand(url) || promptToCopyManually(url);\n}","preventionTips":["Always serve Den web over HTTPS; clipboard requires a secure context","Add allow=\"clipboard-write\" to iframes embedding the app","Feature-detect navigator.clipboard and render a manual copy field as fallback","Test the copy flow in in-app webviews and non-Chromium browsers"],"tags":["browser","clipboard","permissions","den-web"],"backgroundTag":"clipboard-unavailable","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}