Summary
Several copy buttons can crash with a runtime error when the browser does not expose navigator.clipboard:
Runtime TypeError: Cannot read properties of undefined (reading writeText)
The root cause appears to be repeated unsafe Clipboard API access. In multiple use-copy-to-clipboard hooks, the guard checks navigator.clipboard.writeText directly, so it still throws when navigator.clipboard itself is undefined.
Why this happens
navigator.clipboard is only available in secure contexts and may be missing in HTTP, some WebViews, iframes, or restricted browser environments. The code should feature-detect navigator.clipboard?.writeText before calling it, and ideally use a fallback for unsupported contexts.
Locations found
Unsafe duplicated hooks:
workspace/frontend/hooks/use-copy-to-clipboard.ts
packages/go/web/hooks/use-copy-to-clipboard.ts
sdk/studio/src/hooks/use-copy-to-clipboard.ts
Direct navigator.clipboard.writeText(...) calls in the workspace frontend:
workspace/frontend/components/chat/chat-message.tsx
workspace/frontend/components/layout/sidebar-content.tsx
workspace/frontend/components/connect/connect-agent-view.tsx
Direct calls in packages/go/web:
packages/go/web/components/chat/chat-message.tsx
packages/go/web/components/layout/workspace-switcher-menu.tsx
Direct calls in sdk/studio:
sdk/studio/src/components/chat/CodeBlock.tsx
sdk/studio/src/pages/admin/TransportConfig.tsx
sdk/studio/src/pages/serviceagents/components/ServiceAgentDetail.tsx
sdk/studio/src/stores/llmLogStore.ts already has fallback after catch, but still attempts the unsafe call first
Related renderer calls in packages/launcher/src/renderer:
packages/launcher/src/renderer/pages/workspaces/index.tsx
packages/launcher/src/renderer/pages/logs/index.tsx
packages/launcher/src/renderer/components/chat/Markdown.tsx
packages/launcher/src/renderer/components/agent-detail/AgentQuickStart.tsx
packages/launcher/src/renderer/components/agent-detail/AgentDetail.tsx
packages/launcher/src/renderer/components/credentials/CredentialCard.tsx
Some existing code already has the safer pattern and can be used as reference:
sdk/studio/src/pages/admin/ConnectionGuide.tsx
sdk/studio/src/pages/admin/components/dashboard/NetworkStatusPanel.tsx
Suggested fix
Introduce a shared safe copy helper, for example:
async function copyTextToClipboard(text: string) {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
return;
}
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.position = "fixed";
textarea.style.left = "-9999px";
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
}
Then update the three duplicated hooks and direct call sites to use it.
Expected behavior
Clicking copy buttons should not crash the UI when Clipboard API is unavailable. It should either copy via fallback or show a controlled failure toast.
Summary
Several copy buttons can crash with a runtime error when the browser does not expose
navigator.clipboard:The root cause appears to be repeated unsafe Clipboard API access. In multiple
use-copy-to-clipboardhooks, the guard checksnavigator.clipboard.writeTextdirectly, so it still throws whennavigator.clipboarditself isundefined.Why this happens
navigator.clipboardis only available in secure contexts and may be missing in HTTP, some WebViews, iframes, or restricted browser environments. The code should feature-detectnavigator.clipboard?.writeTextbefore calling it, and ideally use a fallback for unsupported contexts.Locations found
Unsafe duplicated hooks:
workspace/frontend/hooks/use-copy-to-clipboard.tspackages/go/web/hooks/use-copy-to-clipboard.tssdk/studio/src/hooks/use-copy-to-clipboard.tsDirect
navigator.clipboard.writeText(...)calls in the workspace frontend:workspace/frontend/components/chat/chat-message.tsxworkspace/frontend/components/layout/sidebar-content.tsxworkspace/frontend/components/connect/connect-agent-view.tsxDirect calls in
packages/go/web:packages/go/web/components/chat/chat-message.tsxpackages/go/web/components/layout/workspace-switcher-menu.tsxDirect calls in
sdk/studio:sdk/studio/src/components/chat/CodeBlock.tsxsdk/studio/src/pages/admin/TransportConfig.tsxsdk/studio/src/pages/serviceagents/components/ServiceAgentDetail.tsxsdk/studio/src/stores/llmLogStore.tsalready has fallback after catch, but still attempts the unsafe call firstRelated renderer calls in
packages/launcher/src/renderer:packages/launcher/src/renderer/pages/workspaces/index.tsxpackages/launcher/src/renderer/pages/logs/index.tsxpackages/launcher/src/renderer/components/chat/Markdown.tsxpackages/launcher/src/renderer/components/agent-detail/AgentQuickStart.tsxpackages/launcher/src/renderer/components/agent-detail/AgentDetail.tsxpackages/launcher/src/renderer/components/credentials/CredentialCard.tsxSome existing code already has the safer pattern and can be used as reference:
sdk/studio/src/pages/admin/ConnectionGuide.tsxsdk/studio/src/pages/admin/components/dashboard/NetworkStatusPanel.tsxSuggested fix
Introduce a shared safe copy helper, for example:
Then update the three duplicated hooks and direct call sites to use it.
Expected behavior
Clicking copy buttons should not crash the UI when Clipboard API is unavailable. It should either copy via fallback or show a controlled failure toast.