angular/components · error · Error
Could not sanitize HTML: ${html}
Error message
Could not sanitize HTML: ${html} What it means
_setInnerHtml sanitizes a SafeHtml value via DomSanitizer before assigning it to element.innerHTML (used by the LiveAnnouncer's announce). If sanitizer.sanitize returns null, the value could not be made safe and the assignment is aborted with this dev-mode error to avoid injecting unsafe markup.
Source
Thrown at src/cdk/private/inner-html.ts:22
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import {SecurityContext} from '@angular/core';
import {DomSanitizer, SafeHtml} from '@angular/platform-browser';
import {trustedHTMLFromString} from './trusted-types';
// !!!Note!!! this file isn't synced into g3, but is replaced with a version that uses
// internal-specific APIs. The internal version may have to be updated if the signature of
// the function changes.
/** Sanitizes and sets the `innerHTML` of an element. */
export function _setInnerHtml(element: HTMLElement, html: SafeHtml, sanitizer: DomSanitizer): void {
const cleanHtml = sanitizer.sanitize(SecurityContext.HTML, html);
if (cleanHtml === null && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw new Error(`Could not sanitize HTML: ${html}`);
}
element.innerHTML = trustedHTMLFromString(cleanHtml || '') as unknown as string;
}
View on GitHub (pinned to 0411926e7d)
Solutions
- Pass plain text to announce() — it doesn't need HTML sanitization for normal announcements.
- If HTML is intentional, wrap it with sanitizer.bypassSecurityTrustHtml only for fully trusted, reviewed content.
- Inspect the failing html value in the error message and fix whatever produces an unsanitizable value.
- Upgrade/verify Angular sanitizer behavior if the same content previously worked.
Example fix
// before announcer.announce(someUserHtml, 'assertive'); // after announcer.announce(plainTextMessage, 'assertive');
Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof html !== 'string' && !isSafeHtmlLike(html)) {
throw new Error('announce expects a plain string or a trusted SafeHtml value');
} Try / catch
try {
announcer.announce(message);
} catch (e) {
if ((e as Error).message.startsWith('Could not sanitize HTML')) {
announcer.announce(stripHtml(message));
} else throw e;
} Prevention
- Announce plain text, not HTML.
- Never build SafeHtml from untrusted input; reserve bypassSecurityTrustHtml for audited static markup.
- Keep the announced strings simple and free of markup after transformations.
When it happens
Trigger: Calling announce(text) where the text resolves to unsafe/bypassed HTML that the sanitizer refuses (e.g. a value created via bypassSecurityTrustHtml in an inconsistent state, or a non-SafeHtml value that sanitizes to null, such as certain malformed/oversized inputs).
Common situations: Passing raw (non-trusted) strings into APIs expecting SafeHtml; custom announcer code reusing _setInnerHtml with user input that fails sanitization; version changes in sanitizer behavior making previously-accepted HTML return null.
Related errors
- ListKeyManager constructed with a signal must receive an inj
- KeyManager items in typeahead mode must implement the `getLa
- CdkDropList could not find an element container matching the
- Invalid DOM structure for drop list. Alternate container ele
- Invalid DOM structure for drop list. All items must be place
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/c8d5d6fd78064e97.
Report an issue: GitHub.