angular/components · error

xPosition value must be either 'before' or after'. Exa

Error message

xPosition value must be either 'before' or after'.
      Example: <mat-menu xPosition="before" #menu="matMenu"></mat-menu>

What it means

MatMenu validates the xPosition input against 'before' | 'after'. Any other value makes the positioning math invalid, so the xPosition setter calls throwMatMenuInvalidPositionX, whose message (noting the missing opening quote on "after'") shows usage.

Source

Thrown at src/material/menu/menu-errors.ts:15

/**
 * @license
 * Copyright Google LLC All Rights Reserved.
 *
 * 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
 */

/**
 * Throws an exception for the case when menu's x-position value isn't valid.
 * In other words, it doesn't match 'before' or 'after'.
 * @docs-private
 */
export function throwMatMenuInvalidPositionX() {
  throw Error(`xPosition value must be either 'before' or after'.
      Example: <mat-menu xPosition="before" #menu="matMenu"></mat-menu>`);
}

/**
 * Throws an exception for the case when menu's y-position value isn't valid.
 * In other words, it doesn't match 'above' or 'below'.
 * @docs-private
 */
export function throwMatMenuInvalidPositionY() {
  throw Error(`yPosition value must be either 'above' or below'.
      Example: <mat-menu yPosition="above" #menu="matMenu"></mat-menu>`);
}

/**
 * Throws an exception for the case when a menu is assigned
 * to a trigger that is placed inside the same menu.
 * @docs-private
 */

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Use xPosition="before" or xPosition="after" literally.
  2. For bound values, constrain the type: xPosition: 'before' | 'after' and guard config defaults (xPosition ?? 'after').
  3. Validate external config before passing into the template.

Example fix

// before
<mat-menu [xPosition]="menu.x"></mat-menu> <!-- menu.x = 'left' -->
// after
<mat-menu [xPosition]="menu.x === 'left' ? 'before' : 'after'"></mat-menu>
Defensive patterns

Strategy: validation

Validate before calling

type MenuXPosition = 'before' | 'after';
function isXPosition(v: unknown): v is MenuXPosition {
  return v === 'before' || v === 'after';
}
const x = isXPosition(config.x) ? config.x : 'after';
// template: <mat-menu [xPosition]="x">

Type guard

function isMenuXPosition(v: unknown): v is 'before' | 'after' {
  return v === 'before' || v === 'after';
}

Try / catch

try {
  menu.xPosition = config.x as 'before' | 'after';
} catch (e) {
  if ((e as Error).message.includes('xPosition value must be')) {
    console.warn(`Invalid xPosition "${config.x}", defaulting to 'after'`);
    menu.xPosition = 'after';
  } else { throw e; }
}

Prevention

When it happens

Trigger: Setting <mat-menu xPosition="left">, xPosition="right", or a bound [xPosition]="expr" where expr is null/undefined/typo.

Common situations: Typing CSS-like values ('left'/'right') instead of Material's vocabulary; binding from config data that defaults to null before load; renaming refactor that introduced casing mismatch ('Before').

Related errors


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