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

  1. Pass plain text to announce() — it doesn't need HTML sanitization for normal announcements.
  2. If HTML is intentional, wrap it with sanitizer.bypassSecurityTrustHtml only for fully trusted, reviewed content.
  3. Inspect the failing html value in the error message and fix whatever produces an unsanitizable value.
  4. 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

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


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/c8d5d6fd78064e97. Report an issue: GitHub.