angular/components · error · Error

Unsupported MatButton appearance "${appearance}"

Error message

Unsupported MatButton appearance "${appearance}"

What it means

MatButton (and its variants like MatIconButton/MatFab) validates the appearance input against a known set of appearances with associated CSS classes. This dev-mode error is thrown when setAppearance receives a value not in APPEARANCE_CLASSES, i.e. an unsupported appearance string.

Source

Thrown at src/material/button/button.ts:79

    // cause the fallback appearance's classes to be set and then immediately replaced when
    // the input value is assigned.
    if (inferredAppearance) {
      this.setAppearance(inferredAppearance);
    }
  }

  /** Programmatically sets the appearance of the button. */
  setAppearance(appearance: MatButtonAppearance): void {
    if (appearance === this._appearance) {
      return;
    }

    const classList = this._elementRef.nativeElement.classList;
    const previousClasses = this._appearance ? APPEARANCE_CLASSES.get(this._appearance) : null;
    const newClasses = APPEARANCE_CLASSES.get(appearance)!;

    if ((typeof ngDevMode === 'undefined' || ngDevMode) && !newClasses) {
      throw new Error(`Unsupported MatButton appearance "${appearance}"`);
    }

    if (previousClasses) {
      classList.remove(...previousClasses);
    }

    classList.add(...newClasses);
    this._appearance = appearance;
  }
}

/** Infers the button's appearance from its static attributes. */
function _inferAppearance(button: HTMLElement): MatButtonAppearance | null {
  if (button.hasAttribute('mat-raised-button')) {
    return 'elevated';
  }

  if (button.hasAttribute('mat-stroked-button')) {

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Use a supported appearance value: 'text', 'filled', 'elevated', 'outlined', or 'tonal'
  2. Fix typos in the appearance attribute or binding
  3. Check the MatButtonAppearance type and rely on TypeScript strictTemplates to catch invalid values at compile time

Example fix

// before
<button mat-button appearance="outline">Save</button>
// after
<button mat-button appearance="outlined">Save</button>
Defensive patterns

Strategy: validation

Validate before calling

const VALID = ['text','filled','elevated','outlined','tonal'] as const;
if (!VALID.includes(appearance as any)) {
  throw new TypeError(`appearance must be one of ${VALID.join(', ')}`);
}

Type guard

type MatButtonAppearance = 'text'|'filled'|'elevated'|'outlined'|'tonal';
function isAppearance(v: string): v is MatButtonAppearance {
  return ['text','filled','elevated','outlined','tonal'].includes(v);
}

Try / catch

// Bind via typed input so runtime throw surfaces in dev; or guard before set:
if (isAppearance(userAppearance)) { btn.appearance = userAppearance; }
else { console.error('Unsupported appearance', userAppearance); }

Prevention

When it happens

Trigger: Setting the appearance input to an invalid value, e.g. <button mat-button appearance="outline"> (typo for 'outlined'), or binding appearance programmatically to a wrong string like 'filled' on a variant that doesn't support it.

Common situations: Copy-pasting appearance names between libraries (e.g. 'outline' from other UI kits); typos ('outln', 'text ' with space); migrating between Material versions where valid appearance values changed.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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