angular/components · error

There can only be one default row without a when predicate f

Error message

There can only be one default row without a when predicate function.

What it means

CdkTree allows at most one node definition without a `when` predicate, which serves as the default/fallback node renderer. When multiple default node defs are found during content check, the tree cannot decide which to use and throws getTreeMultipleDefaultNodeDefsError (dev mode only).

Source

Thrown at src/cdk/tree/tree.ts:314

    // In certain tests, the tree might be destroyed before this is initialized
    // in `ngAfterContentInit`.
    this._keyManager?.destroy();
  }

  ngOnInit() {
    this._checkTreeControlUsage();
    this._initializeDataDiffer();
  }

  ngAfterViewInit() {
    this._viewInit = true;
  }

  private _updateDefaultNodeDefinition() {
    const defaultNodeDefs = this._nodeDefs.filter(def => !def.when);
    if (defaultNodeDefs.length > 1 && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw getTreeMultipleDefaultNodeDefsError();
    }
    this._defaultNodeDef = defaultNodeDefs[0];
  }

  /**
   * Sets the node type for the tree, if it hasn't been set yet.
   *
   * This will be called by the first node that's rendered in order for the tree
   * to determine what data transformations are required.
   */
  _setNodeTypeIfUnset(newType: 'flat' | 'nested') {
    const currentType = this._nodeType.value;

    if (currentType === null) {
      this._nodeType.next(newType);
    } else if ((typeof ngDevMode === 'undefined' || ngDevMode) && currentType !== newType) {
      console.warn(
        `Tree is using conflicting node types which can cause unexpected behavior. ` +

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Add a distinct `when` predicate to all but one node definition, e.g. [cdkNodeDef]="let node; when: isFile"
  2. Keep exactly one catch-all node def without `when`
  3. Audit all cdk-node-def/matTreeNodeDef children of the tree for missing when bindings
  4. If templates come from a shared library, ensure the consuming tree only receives one default def

Example fix

// before
<cdk-node-def *cdkNodeDef="let node">Folder: {{node.name}}</cdk-node-def>
<cdk-node-def *cdkNodeDef="let node">File: {{node.name}}</cdk-node-def>
// after
<cdk-node-def *cdkNodeDef="let node; when: isFolder">Folder: {{node.name}}</cdk-node-def>
<cdk-node-def *cdkNodeDef="let node">File: {{node.name}}</cdk-node-def>
Defensive patterns

Strategy: validation

Validate before calling

// at content-init time, before rendering the tree
const nodeDefs = getDirectives(treeEl, CdkNodeDef) /* or inspect QueryList in custom code */;
const defaults = nodeDefs.filter(d => !d.when);
if (defaults.length > 1) {
  throw new Error('Only one node def may omit a `when` predicate');
}

Type guard

interface ValidNodeDefConfig { when?: (data: any, index: number) => boolean; }
function hasSingleDefault(defs: ValidNodeDefConfig[]): defs is [ValidNodeDefConfig, ...ValidNodeDefConfig[]] & { 0: ValidNodeDefConfig } {
  return defs.filter(d => !d.when).length <= 1;
}

Try / catch

import { getTreeMultipleDefaultNodeDefsError } from '@angular/cdk/tree';
try {
  tree.ngAfterContentChecked();
} catch (e) {
  if ((e as Error).message.includes('one default row without a when')) {
    console.error('Add a when predicate to all but one cdk-node-def');
  }
  throw e;
}

Prevention

When it happens

Trigger: Declaring two or more <cdk-node-def> (or mat-tree node templates) without a when function inside a single <cdk-tree>; ngAfterContentChecked -> _updateDefaultNodeDefinition detects defaultNodeDefs.length > 1.

Common situations: Copy-pasting node templates and forgetting to add a when predicate; refactoring conditions off a node def leaving two unconditional defs; nested trees or templates hoisted via NgTemplateOutlet causing multiple content children to match.

Related errors


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