angular/components · error · Error
setContenteditableValue can only be called on a `contentedit
Error message
setContenteditableValue can only be called on a `contenteditable` element.
What it means
SeleniumWebDriverElement.setContenteditableValue in src/cdk/testing/selenium-webdriver/selenium-web-driver-element.ts guards the same way as the Protractor variant: it reads the contenteditable attribute and throws this Error if the element is not editable (attribute missing or not ''/true/plaintext-only). Only editable elements may have their textContent set through this API; it then executes the set script and stabilizes the harness environment.
Source
Thrown at src/cdk/testing/selenium-webdriver/selenium-web-driver-element.ts:163
return this._executeScript(
(element: Element) => (element.textContent || '').trim(),
this.element(),
);
}
/**
* Sets the value of a `contenteditable` element.
* @param value Value to be set on the element.
*/
async setContenteditableValue(value: string): Promise<void> {
const contenteditableAttr = await this.getAttribute('contenteditable');
if (
contenteditableAttr !== '' &&
contenteditableAttr !== 'true' &&
contenteditableAttr !== 'plaintext-only'
) {
throw new Error('setContenteditableValue can only be called on a `contenteditable` element.');
}
await this._stabilize();
return this._executeScript(
(element: Element, valueToSet: string) => (element.textContent = valueToSet),
this.element(),
value,
);
}
/** Gets the value for the given attribute from the element. */
async getAttribute(name: string): Promise<string | null> {
await this._stabilize();
return this._executeScript(
(element: Element, attribute: string) => element.getAttribute(attribute),
this.element(),
name,
);View on GitHub (pinned to 0411926e7d)
Solutions
- Verify the element has contenteditable="true"/"plaintext-only" at the time of the call (check via getAttribute('contenteditable')).
- For inputs/textareas use sendKeys or the appropriate input-value APIs instead of setContenteditableValue.
- If editability is conditional, put the component into edit mode (or wait for the attribute) before invoking the method.
- Re-query the element after DOM updates so you operate on the current editable node.
Example fix
// before
await element.setContenteditableValue('updated text');
// after
if ((await element.getAttribute('contenteditable')) === 'true') {
await element.setContenteditableValue('updated text');
} Defensive patterns
Strategy: validation
Validate before calling
const editable = await element.getAttribute('contenteditable');
if (editable !== 'true' && editable !== 'plaintext-only' && editable !== '') {
throw new Error(`Cannot setContenteditableValue: contenteditable="${editable}"`);
} Type guard
function isEditable(v: string | null): v is 'true' | 'plaintext-only' | '' {
return v === 'true' || v === 'plaintext-only' || v === '';
} Try / catch
try {
await element.setContenteditableValue(value);
} catch (e) {
if (String(e.message).includes('setContenteditableValue can only be called')) {
console.warn('Target is not contenteditable; falling back to sendKeys.');
await element.sendKeys(value);
} else throw e;
} Prevention
- Ensure the component applies contenteditable before the E2E step runs (wait for edit mode).
- Use explicit attribute waits/expectations in Selenium flows before editing text.
- Keep separate helper methods for form controls vs contenteditable regions.
- Re-locate elements after DOM changes to avoid stale, non-editable references.
When it happens
Trigger: Calling setContenteditableValue on a Selenium-WebDriver-backed TestElement where the DOM node has no contenteditable attribute or contenteditable="false" — e.g. targeting an <input>, a <textarea>, or a div whose editability is toggled off.
Common situations: E2E suites mixing up form control APIs with contenteditable APIs; testing custom editors where contenteditable is applied conditionally (e.g. only in edit mode); stale element references captured before the attribute was applied.
Related errors
- setContenteditableValue can only be called on a `contentedit
- setContenteditableValue can only be called on a `contentedit
- Cannot retrieve popup content because the combobox is closed
- Could not find tab matching filters: ${JSON.stringify(filter
- ListKeyManager constructed with a signal must receive an inj
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/a7b2691dae663085.
Report an issue: GitHub.