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

  1. Trigger the copy from a real user gesture (click handler)
  2. Use the modern Clipboard API manually: navigator.clipboard.writeText(text)
  3. Serve the page over HTTPS/localhost so clipboard permissions are granted
  4. 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

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.