zenorocha/clipboard.js · error · Error
Invalid "target" attribute. Please use "readonly" instead of
Error message
Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute
What it means
Thrown when `action` is 'copy' and the target DOM element carries a `disabled` attribute. Disabled form controls are not selectable and have no selectable value, so the library refuses to copy from them and tells you to use `readonly` instead, which keeps the field selectable while still non-editable.
Source
Thrown at src/actions/default.js:22
/**
* Inner function which performs selection from either `text` or `target`
* properties and then executes copy or cut operations.
* @param {Object} options
*/
const ClipboardActionDefault = (options = {}) => {
// Defines base properties passed from constructor.
const { action = 'copy', container, target, text } = options;
// Sets the `action` to be performed which can be either 'copy' or 'cut'.
if (action !== 'copy' && action !== 'cut') {
throw new Error('Invalid "action" value, use either "copy" or "cut"');
}
// 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.View on GitHub (pinned to 899378dee9)
Solutions
- Replace the `disabled` attribute on the target with `readonly` — readonly fields remain selectable and copyable while preventing edits.
- If the field must stay disabled for form-submission reasons, copy via the `text` callback instead of the `target` selector: `new ClipboardJS(btn, { text: () => field.value })`.
- Dynamically swap `disabled` for `readonly` (or remove it) in the trigger's click handler before the clipboard action runs.
- If disabled state is essential, render a separate non-disabled mirror element (e.g., a read-only span) and point the target at it.
Example fix
// before <input id="token" value="abc123" disabled /> <button class="btn" data-clipboard-target="#token">Copy</button> // after <input id="token" value="abc123" readonly /> <button class="btn" data-clipboard-target="#token">Copy</button>
Defensive patterns
Strategy: validation
Validate before calling
function canCopyFrom(el) {
if (!el || el.nodeType !== 1) return false;
if (el.hasAttribute('disabled')) return false;
return true;
}
const el = document.querySelector('#token');
if (!canCopyFrom(el)) {
// use text callback or swap to readonly before copying
new ClipboardJS(btn, { text: () => el.value });
} else {
new ClipboardJS(btn, { target: () => el });
} Type guard
/**
* @param {Element} el
* @returns {boolean}
*/
function isCopyableElement(el) {
return el instanceof Element && el.nodeType === 1 && !el.hasAttribute('disabled');
} Try / catch
try {
ClipboardActionDefault({ action: 'copy', target: el });
} catch (err) {
if (/use "readonly" instead of "disabled"/.test(err.message)) {
// fall back to reading the value directly via the text path
ClipboardActionCopy(el.value, { container });
} else {
throw err;
}
} Prevention
- Prefer `readonly` over `disabled` for any field a user might copy from.
- Bind copy buttons via the `text` callback when the source field's editable state is dynamic.
- Audit copy targets at render time and disable the copy button itself when the field is disabled.
- Keep a single source of truth for which fields are editable vs. selectable.
When it happens
Trigger: Copying from an `<input>`/`<textarea>` that is `<input disabled ...>` with `new ClipboardJS(el, { text: () => field.value })` won't hit this, but using a `target` selector pointing at `document.querySelector('input[disabled]')` with the default copy action will; binding `data-clipboard-target="#myDisabled"` on a trigger where `#myDisabled` is a disabled input; copying directly via `ClipboardActionDefault({ action: 'copy', target: disabledEl })`.
Common situations: Form fields that toggle between disabled and readonly states (e.g., a disabled submit-time input the user wants to copy); copy buttons on grayed-out fields in admin UIs; migrating from native `disabled` styling to clipboard copy without changing the attribute; ARIA-correct disabled controls that also set the HTML disabled attribute.
Related errors
- Invalid "target" attribute. You can't cut text from elements
- Invalid "target" value, use a valid Element
- Invalid "action" value, use either "copy" or "cut"
AI-assisted analysis of zenorocha/clipboard.js@899378dee9 (2026-08-13).
Data as JSON: /api/errors/ead2864c0884163a.
Report an issue: GitHub.