angular/components · error · Error

MatFormField: Invalid appearance "${newAppearance}", valid v

Error message

MatFormField: Invalid appearance "${newAppearance}", valid values are "fill" or "outline".

What it means

MatFormField's appearance setter validates that the resolved appearance is 'fill' or 'outline' and throws in dev mode otherwise. The value may come from the input binding, MatFormFieldDefaultOptions, or the DEFAULT_APPEARANCE fallback, so a bad default can also trigger it. It protects against silently rendering an unsupported form-field style.

Source

Thrown at src/material/form-field/form-field.ts:276

      // For backwards compatibility. Custom form field controls or directives might set
      // the "floatLabel" input and expect the form field view to be updated automatically.
      // e.g. autocomplete trigger. Ideally we'd get rid of this and the consumers would just
      // emit the "stateChanges" observable. TODO(devversion): consider removing.
      this._changeDetectorRef.markForCheck();
    }
  }
  private _floatLabel!: FloatLabelType;

  /** The form field appearance style. */
  @Input()
  get appearance(): MatFormFieldAppearance {
    return this._appearanceSignal();
  }
  set appearance(value: MatFormFieldAppearance) {
    const newAppearance = value || this._defaults?.appearance || DEFAULT_APPEARANCE;
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      if (newAppearance !== 'fill' && newAppearance !== 'outline') {
        throw new Error(
          `MatFormField: Invalid appearance "${newAppearance}", valid values are "fill" or "outline".`,
        );
      }
    }
    this._appearanceSignal.set(newAppearance);
  }
  private _appearanceSignal = signal<MatFormFieldAppearance>(DEFAULT_APPEARANCE);

  /**
   * Whether the form field should reserve space for one line of hint/error text (default)
   * or to have the spacing grow from 0px as needed based on the size of the hint/error content.
   * Note that when using dynamic sizing, layout shifts will occur when hint/error text changes.
   */
  @Input()
  get subscriptSizing(): SubscriptSizing {
    return this._subscriptSizing || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
  }
  set subscriptSizing(value: SubscriptSizing) {

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Change the value to 'fill' or 'outline'
  2. Check MAT_FORM_FIELD_DEFAULT_OPTIONS for an outdated appearance value and update it
  3. If migrating from 'standard', choose 'outline' (closest visual equivalent) or 'fill'
  4. Note validation only runs in dev mode (ngDevMode); verify with a production build whether it silently misbehaves

Example fix

// before
<mat-form-field appearance="standard">
// after
<mat-form-field appearance="outline">
Defensive patterns

Strategy: validation

Validate before calling

const VALID_APPEARANCES = ['fill', 'outline'] as const;
function isValidAppearance(v: unknown): v is 'fill' | 'outline' {
  return typeof v === 'string' && (VALID_APPEARANCES as readonly string[]).includes(v);
}
const appearance = options.appearance;
if (appearance != null && !isValidAppearance(appearance)) {
  throw new Error(`appearance must be 'fill' or 'outline', got: ${appearance}`);
}

Type guard

function isMatFormFieldAppearance(v: unknown): v is 'fill' | 'outline' {
  return v === 'fill' || v === 'outline';
}

Try / catch

try {
  field.appearance = userAppearance as MatFormFieldAppearance;
} catch (e) {
  if (String(e?.message).includes('Invalid appearance')) {
    console.warn(`Unsupported appearance "${userAppearance}"; using "outline"`);
    field.appearance = 'outline';
  } else throw e;
}

Prevention

When it happens

Trigger: Binding [appearance]="'standard'" (removed in newer Angular Material versions) or any string other than 'fill'/'outline'; setting appearance: 'legacy'/'standard' in MAT_FORM_FIELD_DEFAULT_OPTIONS; passing a misspelled or dynamically-computed value.

Common situations: Upgrading from Angular Material <15 where 'legacy', 'standard', 'outline' were valid — code or theme defaults now fail validation; a config object read from JSON/env supplying an invalid appearance; typos like 'filled'.

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/296203e1f62ffa61. Report an issue: GitHub.