{"record":{"id":"b5c324c83828441d","repo":"angular/components","slug":"there-can-only-be-one-default-row-without-a-when-p","errorCode":null,"errorMessage":"There can only be one default row without a when predicate function. Or set `multiTemplateDataRows`.","messagePattern":"There can only be one default row without a when predicate function\\. Or set `multiTemplateDataRows`\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cdk/table/table.ts","lineNumber":1158,"sourceCode":"    );\n    this._rowDefs = mergeArrayAndSet(this._getOwnDefs(this._contentRowDefs), this._customRowDefs);\n\n    // After all row definitions are determined, find the row definition to be considered default.\n    const defaultRowDefs = this._rowDefs.filter(def => !def.when);\n\n    if (typeof ngDevMode === 'undefined' || ngDevMode) {\n      // At the moment of writing, it's tricky to support `when` with virtual scrolling\n      // because we reuse templates and they can change arbitrarily based on the `when`\n      // condition. We may be able to support it in the future (see #32670).\n      if (this._virtualScrollEnabled() && this._rowDefs.some(def => def.when)) {\n        throw new Error(\n          'Conditional row definitions via the `when` input are not ' +\n            'supported when virtual scrolling is enabled, at the moment.',\n        );\n      }\n\n      if (!this.multiTemplateDataRows && defaultRowDefs.length > 1) {\n        throw getTableMultipleDefaultRowDefsError();\n      }\n    }\n    this._defaultRowDef = defaultRowDefs[0];\n  }\n\n  /**\n   * Check if the header, data, or footer rows have changed what columns they want to display or\n   * whether the sticky states have changed for the header or footer. If there is a diff, then\n   * re-render that section.\n   */\n  private _renderUpdatedColumns(): boolean {\n    const columnsDiffReducer = (acc: boolean, def: BaseRowDef) => {\n      // The differ should be run for every column, even if `acc` is already\n      // true (see #29922)\n      const diff = !!def.getColumnsDiff();\n      return acc || diff;\n    };\n","sourceCodeStart":1140,"sourceCodeEnd":1176,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/table/table.ts#L1140-L1176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\n<tr mat-row *matRowDef=\"let row; columns: cols\"></tr>\n<tr mat-row *matRowDef=\"let row; columns: altCols\"></tr>\n// after\n<tr mat-row *matRowDef=\"let row; columns: cols; when: isSpecial\"></tr>\n<tr mat-row *matRowDef=\"let row; columns: altCols\"></tr>","handlingStrategy":"validation","validationCode":"const defs = Array.from(el.querySelectorAll('tr[matRowDef]'));\nconst defaults = defs.filter(d => !d.getAttribute('matRowDef')?.includes('when'));\nif (defaults.length > 1 && !table.multiTemplateDataRows) {\n  throw new Error('Only one default (no-when) row def allowed, or set multiTemplateDataRows');\n}","typeGuard":"function hasSingleDefaultRowDef(rowDefs: {when?: (d: any) => boolean}[], multi: boolean): boolean {\n  return multi || rowDefs.filter(d => !d.when).length <= 1;\n}","tryCatchPattern":"try {\n  this.cdr.detectChanges();\n} catch (e) {\n  if (/only be one default row/.test(e.message)) {\n    console.error('Add a when predicate to extra row defs or set [multiTemplateDataRows]=true');\n  }\n}","preventionTips":["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"],"tags":["angular","cdk-table","row-def","configuration"],"backgroundTag":"multiple-default-row-defs","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}