nextai-translator/nextai-translator · warning · Error

Clipboard API unavailable

Error message

Clipboard API unavailable

What it means

TranslationHistory's copy button throws 'Clipboard API unavailable' when navigator.clipboard or navigator.clipboard.writeText is missing. The async Clipboard API is only exposed in secure contexts and some webviews/embedded environments omit it entirely, so the guard prevents a TypeError on undefined.writeText.

Source

Thrown at src/common/components/TranslationHistory.tsx:440

                                                }}
                                                overrides={{
                                                    BaseButton: {
                                                        style: { paddingLeft: '6px', paddingRight: '6px' },
                                                    },
                                                }}
                                            >
                                                <MdReplay size={16} />
                                            </Button>
                                        </Tooltip>
                                        <Tooltip content={t('Copy to clipboard')} placement='bottom'>
                                            <Button
                                                size='mini'
                                                kind='tertiary'
                                                onClick={async (event) => {
                                                    event.stopPropagation()
                                                    try {
                                                        if (!navigator?.clipboard?.writeText) {
                                                            throw new Error('Clipboard API unavailable')
                                                        }
                                                        await navigator.clipboard.writeText(item.translatedText)
                                                        toast(t('Copy to clipboard'), {
                                                            duration: 3000,
                                                            icon: '👏',
                                                        })
                                                    } catch (error) {
                                                        console.error(error)
                                                        toast(t('Copy failed'), {
                                                            duration: 3000,
                                                            icon: '⚠️',
                                                        })
                                                    }
                                                }}
                                                overrides={{
                                                    BaseButton: {
                                                        style: { paddingLeft: '6px', paddingRight: '6px' },
                                                    },

View on GitHub (pinned to f57537ee4a)

Solutions

  1. Serve the app over HTTPS (or localhost) so the secure-context Clipboard API is exposed
  2. For Tauri, enable the clipboard-manager plugin/permission and use it as fallback
  3. Use a fallback: document.execCommand('copy') with a hidden textarea when navigator.clipboard is absent
  4. Show the error toast (already caught) advising manual copy

Example fix

// before
await navigator.clipboard.writeText(item.translatedText);
// after
if (navigator?.clipboard?.writeText) {
    await navigator.clipboard.writeText(item.translatedText);
} else {
    const ta = document.createElement('textarea');
    ta.value = item.translatedText;
    document.body.appendChild(ta); ta.select();
    document.execCommand('copy'); ta.remove();
}
Defensive patterns

Strategy: fallback

Validate before calling

const canCopy = typeof navigator !== 'undefined'
    && !!navigator?.clipboard?.writeText
    && (window.isSecureContext || location.hostname === 'localhost');

Type guard

function clipboardAvailable(nav: Navigator | undefined): nav is Navigator & { clipboard: Clipboard } {
    return !!nav?.clipboard && typeof nav.clipboard.writeText === 'function';
}

Try / catch

try {
    await navigator.clipboard.writeText(text);
} catch (e) {
    legacyCopy(text); // textarea + document.execCommand('copy')
}

Prevention

When it happens

Trigger: Clicking the copy button in a non-secure context (http:// page), in a webview without clipboard permission, or in an environment (older browser, some Tauri/extension contexts) where navigator.clipboard is undefined.

Common situations: Testing over http://localhost alternatives; Tauri webview builds without clipboard permission configured; older browsers or embedded WebViews lacking the async clipboard API; permission-policy blocked clipboard in iframes.


AI-assisted analysis of nextai-translator/nextai-translator@f57537ee4a (2026-08-31). Data as JSON: /api/errors/c065f3f893da23e9. Report an issue: GitHub.