angular/components · error

yPosition value must be either 'above' or below'. Exam

Error message

yPosition value must be either 'above' or below'.
      Example: <mat-menu yPosition="above" #menu="matMenu"></mat-menu>

What it means

MatMenu validates yPosition against 'above' | 'below'. The yPosition setter calls throwMatMenuInvalidPositionY when the value differs, so the menu never renders with an ambiguous vertical placement.

Source

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

 */

/**
 * 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
 */
export function throwMatMenuRecursiveError() {
  throw Error(
    `matMenuTriggerFor: menu cannot contain its own trigger. Assign a menu that is ` +
      `not a parent of the trigger or move the trigger outside of the menu.`,
  );
}

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Use yPosition="above" or yPosition="below".
  2. Default bound values: [yPosition]="config.y ?? 'below'".
  3. Type the config field as 'above' | 'below' so TypeScript catches invalid values at compile time.

Example fix

// before
<mat-menu [yPosition]="pos"> <!-- pos: 'top' | 'bottom' -->
// after
<mat-menu [yPosition]="pos === 'top' ? 'above' : 'below'">
Defensive patterns

Strategy: validation

Validate before calling

type MenuYPosition = 'above' | 'below';
function isYPosition(v: unknown): v is MenuYPosition {
  return v === 'above' || v === 'below';
}
const y = isYPosition(config.y) ? config.y : 'below';
// template: <mat-menu [yPosition]="y">

Type guard

function isMenuYPosition(v: unknown): v is 'above' | 'below' {
  return v === 'above' || v === 'below';
}

Try / catch

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

Prevention

When it happens

Trigger: Setting <mat-menu yPosition="top">, yPosition="bottom", or a bound [yPosition]="expr" evaluating to null/undefined/typo at change-detection time.

Common situations: Using CSS vocabulary instead of Material's; bound value arrives asynchronously (initial undefined); casing mismatch ('Above'); mixing up with overlay position strings from CDK.

Related errors


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