From 426a0f1f95c92c016cc65466d8c38e29a9de0efb Mon Sep 17 00:00:00 2001 From: arturovt Date: Tue, 18 Aug 2026 22:49:05 +0300 Subject: [PATCH] fix(cdk/table): show a real error message instead of a crash when a table column is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: if a row used a column that wasn't defined, the app would crash in production with a confusing error like "Cannot read properties of undefined (reading 'headerCell')" — no mention of which column was the problem. This message only showed up in dev mode; in production you just got a raw, useless crash. Now: the table always throws a clear error like `Could not find column with id "column_a".`, in both dev and production, so it's obvious what went wrong and which column to fix. Added a test that forces production mode and checks the table gives the helpful error instead of crashing. --- src/cdk/table/table.spec.ts | 13 +++++++++++++ src/cdk/table/table.ts | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/cdk/table/table.spec.ts b/src/cdk/table/table.spec.ts index d618b79523e6..b76b33a0a368 100644 --- a/src/cdk/table/table.spec.ts +++ b/src/cdk/table/table.spec.ts @@ -688,6 +688,19 @@ describe('CdkTable', () => { ); }); + it('should throw a descriptive error (not a raw TypeError) for an unknown column in production mode', () => { + const originalNgDevMode = (globalThis as any).ngDevMode; + (globalThis as any).ngDevMode = false; + + try { + expect(() => + TestBed.createComponent(MissingColumnDefCdkTableApp).detectChanges(), + ).toThrowError(getTableUnknownColumnError('column_a').message); + } finally { + (globalThis as any).ngDevMode = originalNgDevMode; + } + }); + it('should pick up columns that are indirect descendants', () => { expect(() => TestBed.createComponent(TableWithIndirectDescendantDefs).detectChanges(), diff --git a/src/cdk/table/table.ts b/src/cdk/table/table.ts index 0818d1ef981b..9eb79e193627 100644 --- a/src/cdk/table/table.ts +++ b/src/cdk/table/table.ts @@ -1287,10 +1287,10 @@ export class CdkTable private _addStickyColumnStyles(rows: HTMLElement[], rowDef: BaseRowDef) { const columnDefs = Array.from(rowDef?.columns || []).map(columnName => { const columnDef = this._columnDefsByName.get(columnName); - if (!columnDef && (typeof ngDevMode === 'undefined' || ngDevMode)) { + if (!columnDef) { throw getTableUnknownColumnError(columnName); } - return columnDef!; + return columnDef; }); const stickyStartStates = columnDefs.map(columnDef => columnDef.sticky); const stickyEndStates = columnDefs.map(columnDef => columnDef.stickyEnd); @@ -1415,11 +1415,11 @@ export class CdkTable return Array.from(rowDef.columns, columnId => { const column = this._columnDefsByName.get(columnId); - if (!column && (typeof ngDevMode === 'undefined' || ngDevMode)) { + if (!column) { throw getTableUnknownColumnError(columnId); } - return rowDef.extractCellTemplate(column!); + return rowDef.extractCellTemplate(column); }); }