greensock/GSAP · warning
Copy didn't work; this browser doesn't permit that.
Error message
Copy didn't work; this browser doesn't permit that.
What it means
MotionPathHelper's copy-to-clipboard helper relies on the deprecated document.execCommand('copy'). When the browser refuses (or execCommand throws), it warns that copying is not permitted. The helper catches the exception internally and continues, hiding the copy element afterward.
Source
Thrown at src/MotionPathHelper.js:65
_copyElement.style.display = "none";
_body.appendChild(_copyElement);
},
_parsePath = (path, target, vars) => (_isString(path) && _selectorExp.test(path)) ? _doc.querySelector(path) : Array.isArray(path) ? _rawPathToString(_arrayToRawPath([{x:gsap.getProperty(target, "x"), y:gsap.getProperty(target, "y")}, ...path], vars)) : (_isString(path) || path && (path.tagName + "").toLowerCase() === "path") ? path : 0,
_addCopyToClipboard = (target, getter, onComplete) => {
target.addEventListener('click', e => {
if (e.target._gsHelper) {
let c = getter(e.target);
_copyElement.value = c;
if (c && _copyElement.select) {
console.log(c);
_copyElement.style.display = "block";
_copyElement.select();
try {
_doc.execCommand('copy');
_copyElement.blur();
onComplete && onComplete(target);
} catch (err) {
console.warn("Copy didn't work; this browser doesn't permit that.");
}
_copyElement.style.display = "none";
}
}
});
},
_identityMatrixObject = {matrix:{a:1, b:0, c:0, d:1, e:0, f:0}},
_getConsolidatedMatrix = target => (target.transform.baseVal.consolidate() || _identityMatrixObject).matrix,
_findMotionPathTween = target => {
let tweens = gsap.getTweensOf(target),
i = 0;
for (; i < tweens.length; i++) {
if (tweens[i].vars.motionPath) {
return tweens[i];
} else if (tweens[i].timeline) {
tweens.push(...tweens[i].timeline.getChildren());
}
}View on GitHub (pinned to 13e2b79054)
Solutions
- Trigger the copy from a real user gesture (click handler)
- Use the modern Clipboard API manually: navigator.clipboard.writeText(text)
- Serve the page over HTTPS/localhost so clipboard permissions are granted
- Polyfill/select the text and instruct the user to press Ctrl+C as a fallback
Example fix
// before
// relying on MotionPathHelper's internal execCommand copy
// after
const text = target.getAttribute('d');
if (navigator.clipboard) {
await navigator.clipboard.writeText(text);
} else {
console.warn('Clipboard unavailable; copy manually:', text);
} Defensive patterns
Strategy: fallback
Validate before calling
function canCopy() {
return !!(navigator.clipboard && navigator.clipboard.writeText) || (document.queryCommandSupported && document.queryCommandSupported('copy'));
} Try / catch
try {
await navigator.clipboard.writeText(text);
} catch (err) {
// fallback: select text for manual copy
const ta = document.createElement('textarea');
ta.value = text;
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); } catch (e) { prompt('Copy manually:', text); }
ta.remove();
} Prevention
- Prefer navigator.clipboard.writeText over execCommand
- Only copy inside user-gesture handlers
- Serve over HTTPS/localhost
- Provide a manual-copy fallback in iframes
When it happens
Trigger: Calling the MotionPathHelper copy feature in a browser/context where execCommand('copy') is blocked: no user gesture, iframe without allow, insecure (http) context where clipboard API is restricted, or very old/strict browsers.
Common situations: Clicking the helper's copy button inside a sandboxed iframe or headless test environment; using it in an automated test where no user activation exists; HTTPS-only clipboard policies.
AI-assisted analysis of greensock/GSAP@13e2b79054 (2026-08-29).
Data as JSON: /api/errors/d1b3c6b0be2d43db.
Report an issue: GitHub.