zenorocha/clipboard.js · error · Error
Invalid "target" value, use a valid Element
Error message
Invalid "target" value, use a valid Element
What it means
Thrown when the `target` option is defined (not undefined) but is not a genuine DOM Element. The library checks `typeof target === 'object' && target.nodeType === 1` (ELEMENT_NODE); anything failing that — a string selector, a jQuery/Zepto wrapper, a NodeList, an SVG-non-element node, or `null` passed explicitly — triggers this error. Note: passing `undefined` skips the branch entirely, so the error specifically means a non-Element value was supplied.
Source
Thrown at src/actions/default.js:36
// Sets the `target` property using an element that will be have its content copied.
if (target !== undefined) {
if (target && typeof target === 'object' && target.nodeType === 1) {
if (action === 'copy' && target.hasAttribute('disabled')) {
throw new Error(
'Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'
);
}
if (
action === 'cut' &&
(target.hasAttribute('readonly') || target.hasAttribute('disabled'))
) {
throw new Error(
'Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'
);
}
} else {
throw new Error('Invalid "target" value, use a valid Element');
}
}
// Define selection strategy based on `text` property.
if (text) {
return ClipboardActionCopy(text, { container });
}
// Defines which selection strategy based on `target` property.
if (target) {
return action === 'cut'
? ClipboardActionCut(target)
: ClipboardActionCopy(target, { container });
}
};
export default ClipboardActionDefault;
View on GitHub (pinned to 899378dee9)
Solutions
- Resolve the selector to a real Element before passing it: `target: document.querySelector('#myInput')`.
- If using jQuery, unwrap with `target: $('#myInput')[0]` or `target: $('#myInput').get(0)`.
- Guard against null from querySelector when the element may not exist yet: `const el = document.querySelector(sel); if (el) { ... }`.
- When binding via `data-clipboard-target="selector"`, the library resolves it internally — confirm the selector matches exactly one element that exists in the DOM at click time.
- In React/Vue, pass the raw DOM node from the ref (`ref.current`), not the ref object itself.
Example fix
// before
ClipboardActionDefault({ target: '#myInput' }); // string selector
ClipboardActionDefault({ target: $('#myInput') }); // jQuery wrapper
ClipboardActionDefault({ target: document.querySelector('#missing') }); // null
// after
ClipboardActionDefault({ target: document.querySelector('#myInput') });
ClipboardActionDefault({ target: $('#myInput')[0] }); Defensive patterns
Strategy: type-guard
Validate before calling
function resolveTarget(selectorOrEl) {
if (selectorOrEl instanceof Element) return selectorOrEl;
if (typeof selectorOrEl === 'string') {
return document.querySelector(selectorOrEl) || null;
}
// jQuery-ish wrapper
if (selectorOrEl && selectorOrEl.length && selectorOrEl[0] instanceof Element) {
return selectorOrEl[0];
}
return null;
}
const el = resolveTarget(maybeTarget);
if (!el) throw new Error('Clipboard target not found in DOM'); Type guard
/**
* @param {unknown} v
* @returns {v is Element}
*/
function isDomElement(v) {
return typeof v === 'object' && v !== null && v.nodeType === 1;
} Try / catch
try {
ClipboardActionDefault({ action, target: maybeTarget });
} catch (err) {
if (/use a valid Element/.test(err.message)) {
console.error('Clipboard target was not a DOM Element:', maybeTarget);
// recover: re-resolve from a known selector
const el = document.querySelector('#fallback');
if (el) ClipboardActionDefault({ action, target: el });
} else {
throw err;
}
} Prevention
- Always pass `document.querySelector(sel)` (an Element), never the raw selector string.
- Unwrap jQuery/Zepto collections with `[0]` or `.get(0)` before passing as target.
- Null-check querySelector results — a missing element at runtime is the most common cause.
- In framework code, pass `ref.current` (the DOM node), not the ref container.
- Add a runtime assertion at the call site: `console.assert(target instanceof Element, ...)`.
When it happens
Trigger: Passing `target: '#myInput'` (a CSS selector string) instead of `target: document.querySelector('#myInput')`; passing a jQuery object `target: $('#myInput')` (it's an array-like wrapper, nodeType is undefined); passing a NodeList from `querySelectorAll`; passing `target: null` explicitly; passing a Text node or document fragment (nodeType !== 1).
Common situations: Migrating from jQuery where `$('#id')` was used directly; confusing the `text` (accepts a function/string) and `target` (accepts an Element) options; SSR or test environments where the DOM isn't loaded yet so `document.querySelector` returns null; passing an element reference captured before it was attached; React refs that resolve to a wrapper object.
Related errors
- Invalid "action" value, use either "copy" or "cut"
- Invalid "target" attribute. Please use "readonly" instead of
- Invalid "target" attribute. You can't cut text from elements
AI-assisted analysis of zenorocha/clipboard.js@899378dee9 (2026-08-13).
Data as JSON: /api/errors/fdeabe75e316ff2c.
Report an issue: GitHub.