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. Or set `multiTemplateDataRows`.
What it means
More than one row definition lacks a `when` predicate (i.e. multiple 'default' row defs) while multiTemplateDataRows is false. The table cannot decide which default def to use for a data row. Thrown in _syncRowDefs during content init in dev mode.
Source
Thrown at src/cdk/table/table.ts:1158
);
this._rowDefs = mergeArrayAndSet(this._getOwnDefs(this._contentRowDefs), this._customRowDefs);
// After all row definitions are determined, find the row definition to be considered default.
const defaultRowDefs = this._rowDefs.filter(def => !def.when);
if (typeof ngDevMode === 'undefined' || ngDevMode) {
// At the moment of writing, it's tricky to support `when` with virtual scrolling
// because we reuse templates and they can change arbitrarily based on the `when`
// condition. We may be able to support it in the future (see #32670).
if (this._virtualScrollEnabled() && this._rowDefs.some(def => def.when)) {
throw new Error(
'Conditional row definitions via the `when` input are not ' +
'supported when virtual scrolling is enabled, at the moment.',
);
}
if (!this.multiTemplateDataRows && defaultRowDefs.length > 1) {
throw getTableMultipleDefaultRowDefsError();
}
}
this._defaultRowDef = defaultRowDefs[0];
}
/**
* Check if the header, data, or footer rows have changed what columns they want to display or
* whether the sticky states have changed for the header or footer. If there is a diff, then
* re-render that section.
*/
private _renderUpdatedColumns(): boolean {
const columnsDiffReducer = (acc: boolean, def: BaseRowDef) => {
// The differ should be run for every column, even if `acc` is already
// true (see #29922)
const diff = !!def.getColumnsDiff();
return acc || diff;
};
View on GitHub (pinned to 0411926e7d)
Solutions
- Add a `when` predicate to all but one row def, e.g. *matRowDef="let row; columns: cols; when: isSpecial"
- Set [multiTemplateDataRows]="true" on the table to allow multiple rows per data item
- Remove the redundant default row definition
- If using virtual scrolling, remove when-based row defs (unsupported there)
Example fix
// before <tr mat-row *matRowDef="let row; columns: cols"></tr> <tr mat-row *matRowDef="let row; columns: altCols"></tr> // after <tr mat-row *matRowDef="let row; columns: cols; when: isSpecial"></tr> <tr mat-row *matRowDef="let row; columns: altCols"></tr>
Defensive patterns
Strategy: validation
Validate before calling
const defs = Array.from(el.querySelectorAll('tr[matRowDef]'));
const defaults = defs.filter(d => !d.getAttribute('matRowDef')?.includes('when'));
if (defaults.length > 1 && !table.multiTemplateDataRows) {
throw new Error('Only one default (no-when) row def allowed, or set multiTemplateDataRows');
} Type guard
function hasSingleDefaultRowDef(rowDefs: {when?: (d: any) => boolean}[], multi: boolean): boolean {
return multi || rowDefs.filter(d => !d.when).length <= 1;
} Try / catch
try {
this.cdr.detectChanges();
} catch (e) {
if (/only be one default row/.test(e.message)) {
console.error('Add a when predicate to extra row defs or set [multiTemplateDataRows]=true');
}
} Prevention
- Give every extra row template a when predicate
- Set multiTemplateDataRows explicitly when multiple rows per item are intended
- Don't combine when-based rows with virtual scrolling
When it happens
Trigger: Two or more <tr mat-row *matRowDef="let row; columns: cols;"> without when, and [multiTemplateDataRows] not set to true; note also that when-conditional defs are unsupported with virtual scrolling at this point.
Common situations: Adding a second row template for styling alternates but forgetting when: predicates; wanting multiple row types without enabling multiTemplateDataRows; combining CdkVirtualScrollViewport with when-based rows.
Related errors
- Could not find a matching row definition for the provided ro
- Project name is required.
- Conditional row definitions via the `when` input are not sup
- CDK virtual scroll: maxBufferPx must be greater than or equa
- Error: cdk-virtual-scroll-viewport requires the "itemSize" p
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/b5c324c83828441d.
Report an issue: GitHub.