angular/components · error
Cannot fetch icon from URL "${safeUrl}".
Error message
Cannot fetch icon from URL "${safeUrl}". What it means
_fetchIcon builds the request from iconConfig.url; if that sanitized URL is null (e.g. the config was created without a URL), it throws a template error naming the attempted URL. This guards against config objects that only carry a literal (or nothing) being routed through the URL-fetch path.
Source
Thrown at src/material/icon/icon-registry.ts:641
return svg;
}
/**
* Returns an Observable which produces the string contents of the given icon. Results may be
* cached, so future calls with the same URL may not cause another HTTP request.
*/
private _fetchIcon(iconConfig: SvgIconConfig): Observable<TrustedHTML> {
const {url: safeUrl, options} = iconConfig;
const withCredentials = options?.withCredentials ?? false;
if (!this._httpClient) {
throw getMatIconNoHttpProviderError();
}
// TODO: add an ngDevMode check
if (safeUrl == null) {
throw Error(`Cannot fetch icon from URL "${safeUrl}".`);
}
const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);
// TODO: add an ngDevMode check
if (!url) {
throw getMatIconFailedToSanitizeUrlError(safeUrl);
}
// Store in-progress fetches to avoid sending a duplicate request for a URL when there is
// already a request in progress for that URL. It's necessary to call share() on the
// Observable returned by http.get() so that multiple subscribers don't cause multiple XHRs.
const inProgressFetch = this._inProgressUrlFetches.get(url);
if (inProgressFetch) {
return inProgressFetch;
}
View on GitHub (pinned to 0411926e7d)
Solutions
- Ensure a valid SafeResourceUrl is passed: sanitizer.bypassSecurityTrustResourceUrl('assets/icons.svg').
- Check that the name/namespace passed to addSvgIcon matches what is used in [svgIcon] so the right config is fetched.
- Log the registry config before fetching; replace null entries with real URLs or literal registrations.
Example fix
// before
registry.addSvgIcon('gear', undefined as any);
// after
registry.addSvgIcon('gear', this.sanitizer.bypassSecurityTrustResourceUrl('assets/gear.svg')); Defensive patterns
Strategy: validation
Validate before calling
const url = sanitizer.bypassSecurityTrustResourceUrl('assets/icons.svg');
if (!url || !('changingThisBreaksApplicationSecurity' in url)) {
throw new Error('Icon URL must be a non-null SafeResourceUrl');
}
registry.addSvgIcon('set', url); Type guard
function isSafeResourceUrl(v: unknown): v is SafeResourceUrl {
return !!v && typeof v === 'object' &&
'changingThisBreaksApplicationSecurity' in (v as object);
} Try / catch
try {
await firstValueFrom(registry.getNamedSvgIcon(name));
} catch (e) {
if ((e as Error).message.startsWith('Cannot fetch icon from URL')) {
console.error(`Icon config for "${name}" has no URL; register a literal instead`);
} else { throw e; }
} Prevention
- Never pass undefined/plain string where a SafeResourceUrl is expected
- Keep a single factory provider that builds all icon configs so URLs are set in one place
- Log icon config map in dev mode to catch null URLs early
When it happens
Trigger: Internal path where a SvgIconConfig has url == null when the fetch logic runs — practically caused by calling an API that produced a null/bypassed URL value, e.g. passing undefined/null instead of a SafeResourceUrl into addSvgIcon.
Common situations: Passing a plain string or undefined instead of sanitizer.bypassSecurityTrustResourceUrl(...) and having it coerced to null; config created by addSvgIconLiteral but fetched via the URL path; refactor errors after version upgrades.
Related errors
- The literal provided to MatIconRegistry was not trusted as s
- The URL provided to MatIconRegistry was not trusted as a res
- Unable to find icon with the name "${name}"
- <svg> tag not found
- mat-tab-group background color must be set through the Sass
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/29f0f1b6a11d4e67.
Report an issue: GitHub.