{"record":{"id":"fdeabe75e316ff2c","repo":"zenorocha/clipboard.js","slug":"invalid-target-value-use-a-valid-element","errorCode":null,"errorMessage":"Invalid \"target\" value, use a valid Element","messagePattern":"Invalid \"target\" value, use a valid Element","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/actions/default.js","lineNumber":36,"sourceCode":"  // Sets the `target` property using an element that will be have its content copied.\n  if (target !== undefined) {\n    if (target && typeof target === 'object' && target.nodeType === 1) {\n      if (action === 'copy' && target.hasAttribute('disabled')) {\n        throw new Error(\n          'Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute'\n        );\n      }\n\n      if (\n        action === 'cut' &&\n        (target.hasAttribute('readonly') || target.hasAttribute('disabled'))\n      ) {\n        throw new Error(\n          'Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes'\n        );\n      }\n    } else {\n      throw new Error('Invalid \"target\" value, use a valid Element');\n    }\n  }\n\n  // Define selection strategy based on `text` property.\n  if (text) {\n    return ClipboardActionCopy(text, { container });\n  }\n\n  // Defines which selection strategy based on `target` property.\n  if (target) {\n    return action === 'cut'\n      ? ClipboardActionCut(target)\n      : ClipboardActionCopy(target, { container });\n  }\n};\n\nexport default ClipboardActionDefault;\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/zenorocha/clipboard.js/blob/899378dee9681dcf4cb3d702c23a3f3cd9f473d8/src/actions/default.js#L18-L54","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nClipboardActionDefault({ target: '#myInput' });        // string selector\nClipboardActionDefault({ target: $('#myInput') });       // jQuery wrapper\nClipboardActionDefault({ target: document.querySelector('#missing') }); // null\n// after\nClipboardActionDefault({ target: document.querySelector('#myInput') });\nClipboardActionDefault({ target: $('#myInput')[0] });","handlingStrategy":"type-guard","validationCode":"function resolveTarget(selectorOrEl) {\n  if (selectorOrEl instanceof Element) return selectorOrEl;\n  if (typeof selectorOrEl === 'string') {\n    return document.querySelector(selectorOrEl) || null;\n  }\n  // jQuery-ish wrapper\n  if (selectorOrEl && selectorOrEl.length && selectorOrEl[0] instanceof Element) {\n    return selectorOrEl[0];\n  }\n  return null;\n}\nconst el = resolveTarget(maybeTarget);\nif (!el) throw new Error('Clipboard target not found in DOM');","typeGuard":"/**\n * @param {unknown} v\n * @returns {v is Element}\n */\nfunction isDomElement(v) {\n  return typeof v === 'object' && v !== null && v.nodeType === 1;\n}","tryCatchPattern":"try {\n  ClipboardActionDefault({ action, target: maybeTarget });\n} catch (err) {\n  if (/use a valid Element/.test(err.message)) {\n    console.error('Clipboard target was not a DOM Element:', maybeTarget);\n    // recover: re-resolve from a known selector\n    const el = document.querySelector('#fallback');\n    if (el) ClipboardActionDefault({ action, target: el });\n  } else {\n    throw err;\n  }\n}","preventionTips":["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, ...)`."],"tags":["clipboard","dom","type-mismatch","api-misuse","null-reference"],"backgroundTag":null,"analyzedSha":"899378dee9681dcf4cb3d702c23a3f3cd9f473d8","analyzedAt":"2026-08-13T04:33:09.334Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}