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

  1. Resolve the selector to a real Element before passing it: `target: document.querySelector('#myInput')`.
  2. If using jQuery, unwrap with `target: $('#myInput')[0]` or `target: $('#myInput').get(0)`.
  3. Guard against null from querySelector when the element may not exist yet: `const el = document.querySelector(sel); if (el) { ... }`.
  4. 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.
  5. 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

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


AI-assisted analysis of zenorocha/clipboard.js@899378dee9 (2026-08-13). Data as JSON: /api/errors/fdeabe75e316ff2c. Report an issue: GitHub.