angular/components · error

Table text column must have a name.

Error message

Table text column must have a name.

What it means

MatTextColumn derives a default header text by transforming its `name`; if no name input is provided, _createDefaultHeaderText cannot produce a header and throws in dev mode. The name is also required to register the column with the table.

Source

Thrown at src/cdk/table/text-column.ts:156

      throw getTableTextColumnMissingParentTableError();
    }
  }

  ngOnDestroy() {
    if (this._table) {
      this._table.removeColumnDef(this.columnDef);
    }
  }

  /**
   * Creates a default header text. Use the options' header text transformation function if one
   * has been provided. Otherwise simply capitalize the column name.
   */
  _createDefaultHeaderText() {
    const name = this.name;

    if (!name && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw getTableTextColumnMissingNameError();
    }

    if (this._options && this._options.defaultHeaderTextTransform) {
      return this._options.defaultHeaderTextTransform(name);
    }

    return name[0].toUpperCase() + name.slice(1);
  }

  /** Synchronizes the column definition name with the text column name. */
  private _syncColumnDefName() {
    if (this.columnDef) {
      this.columnDef.name = this.name;
    }
  }
}

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Add the name attribute: <mat-text-column name="userName"></mat-text-column>
  2. Ensure the bound [name] value is set before change detection/ngOnInit (static binding or input setup)
  3. Provide a projected <th mat-header-cell *matHeaderCellDef> instead of relying on the default text
  4. Configure the defaultHeaderTextTransform option only as a transform for existing names, not a substitute for name

Example fix

// before
<mat-text-column></mat-text-column>
// after
<mat-text-column name="email"></mat-text-column>
Defensive patterns

Strategy: validation

Validate before calling

const cols = Array.from(hostEl.querySelectorAll('mat-text-column'));
const unnamed = cols.filter(c => !c.getAttribute('name') && !c.hasAttribute('ng-reflect-name'));
if (unnamed.length) throw new Error('Every mat-text-column requires a name');

Type guard

function hasName(col: {name?: string}): col is {name: string} & typeof col {
  return typeof col.name === 'string' && col.name.length > 0;
}

Try / catch

try {
  this.cdr.detectChanges();
} catch (e) {
  if (/must have a name/.test(e.message)) {
    console.error('Add name="..." to each mat-text-column.');
  }
}

Prevention

When it happens

Trigger: _createDefaultHeaderText (called from ngOnInit): this.name is empty/undefined and no header text is supplied via projected header cell or defaultHeaderTextTransform option.

Common situations: Writing <mat-text-column> and forgetting name="..."; binding [name] to a property that is undefined at init time; dynamically created columns where the name is assigned after ngOnInit already ran.

Related errors


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