angular/angular · error · Error

Error in attribute selector "${attr}". Unescaped "$" is not

Error message

Error in attribute selector "${attr}". Unescaped "$" is not supported. Please escape with "\$".

What it means

unescapeAttribute runs over attribute names parsed from a selector and rejects a '$' that was not preceded by a backslash. Angular uses '$' internally when encoding special attribute prefixes (attr./style./class.), so a raw '$' in an attribute selector is ambiguous; source selectors must write '\$' which this function unescapes.

Source

Thrown at packages/compiler/src/directive_matching.ts:143

   *
   * This is needed because `$` can have a special meaning in CSS selectors,
   * but we might want to match an attribute that contains `$`.
   * [MDN web link for more
   * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
   * @param attr the attribute to unescape.
   * @returns the unescaped string.
   */
  unescapeAttribute(attr: string): string {
    let result = '';
    let escaping = false;
    for (let i = 0; i < attr.length; i++) {
      const char = attr.charAt(i);
      if (char === '\\') {
        escaping = true;
        continue;
      }
      if (char === '$' && !escaping) {
        throw new Error(
          `Error in attribute selector "${attr}". ` +
            `Unescaped "$" is not supported. Please escape with "\\$".`,
        );
      }
      escaping = false;
      result += char;
    }
    return result;
  }

  /**
   * Escape `$` sequences from the CSS attribute selector.
   *
   * This is needed because `$` can have a special meaning in CSS selectors,
   * with this method we are escaping `$` with `\$'.
   * [MDN web link for more
   * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
   * @param attr the attribute to escape.

View on GitHub (pinned to 51cb07e980)

Solutions

  1. Escape the dollar in the selector: '[data-test\$]' (backslash-dollar inside the string literal).
  2. Or rename the attribute to avoid '$' entirely — cleaner for attribute binding and template readability.

Example fix

// before
@Directive({selector: '[data-flag$]'})

// after
@Directive({selector: '[data-flag\$]'}) // '\$' unescapes to a literal '$' attribute
Defensive patterns

Strategy: validation

Validate before calling

const hasUnescapedDollar = (selector: string): boolean =>
  /\[[^\]]*(?<!\\)\$/.test(selector); // '$' inside an attribute selector without a preceding '\'

function assertValidAttributeSelector(selector: string): void {
  if (hasUnescapedDollar(selector)) {
    throw new Error(`Attribute selector "${selector}" contains an unescaped '$'; write '\\$'`);
  }
}

Prevention

When it happens

Trigger: An attribute selector whose attribute name contains an unescaped dollar: '[data-test$]', '[foo$bar="v"]' in a @Directive/@Component selector or ng-content select.

Common situations: Naming conventions that include '$' (observable-style names like count$, data$) leaking into attribute selector names; test attributes generated by tooling.

Related errors


AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22). Data as JSON: /api/errors/27a0d0c2b16f8b00. Report an issue: GitHub.