angular/components · error

Could not find a tree control, levelAccessor, or childrenAcc

Error message

Could not find a tree control, levelAccessor, or childrenAccessor for the tree.

What it means

On init, _checkTreeControlUsage counts how many navigation mechanisms the tree was given: treeControl input, levelAccessor input, or childrenAccessor input. If none is present, the tree has no way to traverse/flatten data and getTreeControlMissingError() is thrown. Exactly one mechanism must be provided.

Source

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

  private _checkTreeControlUsage() {
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      // Verify that Tree follows API contract of using one of TreeControl, levelAccessor or
      // childrenAccessor. Throw an appropriate error if contract is not met.
      let numTreeControls = 0;

      if (this.treeControl) {
        numTreeControls++;
      }
      if (this.levelAccessor) {
        numTreeControls++;
      }
      if (this.childrenAccessor) {
        numTreeControls++;
      }

      if (!numTreeControls) {
        throw getTreeControlMissingError();
      } else if (numTreeControls > 1) {
        throw getMultipleTreeControlsError();
      }
    }
  }

  /** Check for changes made in the data and render each change (node added/removed/moved). */
  renderNodeChanges(
    data: readonly T[],
    dataDiffer: IterableDiffer<T> = this._dataDiffer,
    viewContainer: ViewContainerRef = this._nodeOutlet.viewContainer,
    parentData?: T,
  ) {
    const changes = dataDiffer.diff(data);

    // Some tree consumers expect change detection to propagate to nodes
    // even when the array itself hasn't changed; we explicitly detect changes
    // anyways in order for nodes to update their data.

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Provide exactly one traversal config: pass [treeControl]="treeControl" (FlatTreeControl or NestedTreeControl) to the tree.
  2. Alternatively, for accessor-based trees, pass [levelAccessor]="node => node.level" or [childrenAccessor]="node => node.children".
  3. Check the binding is applied to the tree element itself (not a nested node template) and that spelling/case is correct.
  4. If the tree is rendered conditionally, make sure the config object is created before the component initializes (ngOnInit).

Example fix

// before
<cdk-tree [dataSource]="dataSource">
  <cdk-tree-node *cdkTreeNodeDef="let node">{{node.name}}</cdk-tree-node>
</cdk-tree>

// after
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
  <cdk-tree-node *cdkTreeNodeDef="let node">{{node.name}}</cdk-tree-node>
</cdk-tree>
// or accessor style:
<cdk-tree [dataSource]="dataSource" [levelAccessor]="getLevel">...
Defensive patterns

Strategy: validation

Validate before calling

const controlCount = [+!!(tree as any).treeControl, +!!(tree as any).levelAccessor, +!!(tree as any).childrenAccessor]
  .reduce((a, b) => a + b, 0);
if (controlCount === 0) console.error('cdk-tree needs exactly one of treeControl, levelAccessor, childrenAccessor');

Type guard

function hasTraversalConfig(t: { treeControl?: unknown; levelAccessor?: unknown; childrenAccessor?: unknown }): boolean {
  return !!t.treeControl !== !!t.levelAccessor !== !!t.childrenAccessor ||
    (!!t.treeControl ? 1 : 0) + (!!t.levelAccessor ? 1 : 0) + (!!t.childrenAccessor ? 1 : 0) === 1;
}

Try / catch

try {
  this.tree.ngOnInit();
} catch (e) {
  if (e && String(e.message).includes('tree control, levelAccessor, or childrenAccessor')) {
    this.tree.treeControl = this.treeControl; // provide default
  } else { throw e; }
}

Prevention

When it happens

Trigger: ngOnInit of a <cdk-tree> where none of [treeControl], [levelAccessor], [childrenAccessor] inputs are bound — e.g. <cdk-tree [dataSource]="data"><cdk-tree-node ...>.

Common situations: Copy-pasting a tree template but forgetting the treeControl binding; upgrading Angular CDK (v13+ introduced levelAccessor/childrenAccessor) and removing an old control without adding accessors; building a minimal tree to experiment and omitting all config; typos like [treecontrol].

Related errors


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