angular/components · error · Error
CdkSelection: index required when trackBy is used
Error message
CdkSelection: index required when trackBy is used
What it means
CdkSelection.toggleSelection throws in dev mode when a trackByFn is configured on the CdkSelection but the caller omits the index argument. With track-by, items are identified by trackByFn(index, value), so toggling identity cannot be computed without the index.
Source
Thrown at src/cdk-experimental/selection/selection.ts:143
ngAfterContentChecked() {
if (this._dataSource && !this._renderChangeSubscription) {
this._observeRenderChanges();
}
}
ngOnDestroy() {
this._destroyed.next();
this._destroyed.complete();
if (isDataSource(this._dataSource)) {
this._dataSource.disconnect(this);
}
}
/** Toggles selection for a given value. `index` is required if `trackBy` is used. */
toggleSelection(value: T, index?: number) {
if (!!this.trackByFn && index == null && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('CdkSelection: index required when trackBy is used');
}
if (this.isSelected(value, index)) {
this._selection.deselect({value, index});
} else {
this._selection.select({value, index});
}
}
/**
* Toggles select-all. If no value is selected, select all values. If all values or some of the
* values are selected, de-select all values.
*/
toggleSelectAll() {
if (!this._multiple && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('CdkSelection: multiple selection not enabled');
}
View on GitHub (pinned to 0411926e7d)
Solutions
- Pass the row index: toggleSelection(value, i), e.g., inside *cdkRow or *cdkItem where the index is provided.
- Remove the trackBy input if value-only identity is acceptable.
- Make index required in wrapper helpers so the compiler enforces it.
Example fix
// before selection.toggleSelection(row.value); // after selection.toggleSelection(row.value, row.index);
Defensive patterns
Strategy: validation
Validate before calling
function canToggle(trackByFn: unknown, index?: number): boolean {
return !trackByFn || index != null;
}
if (!canToggle(selection.trackByFn, idx)) throw new Error('toggleSelection requires index when trackBy is set');
selection.toggleSelection(value, idx); Type guard
function hasToggleIndex(value: unknown, index: number | undefined): index is number {
return index != null;
} Try / catch
try {
selection.toggleSelection(value, index);
} catch (e) {
if ((e as Error).message.includes('index required')) {
console.warn('Supply the row index when using trackBy');
} else throw e;
} Prevention
- Call toggleSelection from row templates that expose the index (*cdkRow="let i = index").
- Make wrapper helpers require the index parameter when trackBy is present.
- Remove [trackBy] if toggling by value alone is the intended behavior.
When it happens
Trigger: Calling selection.toggleSelection(value) with no second argument on a CdkSelection that has [trackBy] set. Calling without trackBy is fine.
Common situations: Click handlers bound only to the row value; template method calls like toggleSelection(row) written before trackBy was added; helper functions that drop optional parameters.
Related errors
- SelectionSet: index required when trackByFn is used.
- SelectionSet: not multiple selection
- CdkSelectAll: missing CdkSelection in the parent
- Unknown data source
- CdkSelection: multiple selection not enabled
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/0643b713161d94a6.
Report an issue: GitHub.