angular/components · error · Error
SelectionSet: not multiple selection
Error message
SelectionSet: not multiple selection
What it means
SelectionSet.select() throws this dev-mode assertion when more than one item is passed to select() while the SelectionSet was created in single-selection mode (multiple: false). The API guard exists so callers do not silently get a partially-applied multi-select on a set that only tracks one selection. It only fires in development builds (ngDevMode).
Source
Thrown at src/cdk-experimental/selection/selection-set.ts:62
* on them. Because `trackByFn` requires the index of the item to be passed in, the `index` field is
* expected to be set when calling `isSelected`, `select` and `deselect`.
*/
export class SelectionSet<T> implements TrackBySelection<T> {
private _selectionMap = new Map<T | ReturnType<TrackByFunction<T>>, SelectableWithIndex<T>>();
changed = new Subject<SelectionChange<T>>();
constructor(
private _multiple = false,
private _trackByFn?: TrackByFunction<T>,
) {}
isSelected(value: SelectableWithIndex<T>): boolean {
return this._selectionMap.has(this._getTrackedByValue(value));
}
select(...selects: SelectableWithIndex<T>[]) {
if (!this._multiple && selects.length > 1 && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('SelectionSet: not multiple selection');
}
const before = this._getCurrentSelection();
if (!this._multiple) {
this._selectionMap.clear();
}
const toSelect: SelectableWithIndex<T>[] = [];
for (const select of selects) {
if (this.isSelected(select)) {
continue;
}
toSelect.push(select);
this._markSelected(this._getTrackedByValue(select), select);
}
View on GitHub (pinned to 0411926e7d)
Solutions
- Construct the SelectionSet with { multiple: true } if multi-select is intended.
- Otherwise select items one at a time in a loop (each select() call replaces the previous selection in single mode).
- Guard the call: only call select when the set is multiple, or slice to a single item.
Example fix
// before
const set = new SelectionSet<string>(); // single mode
set.select(...values);
// after
const set = new SelectionSet<string>({ multiple: true });
set.select(...values); Defensive patterns
Strategy: validation
Validate before calling
function canSelect(set: SelectionSet<unknown>, items: unknown[]): boolean {
return set.multiple || items.length <= 1;
}
if (!canSelect(set, values)) throw new Error('Cannot multi-select on a single SelectionSet');
set.select(...values.slice(0, set.multiple ? values.length : 1)); Type guard
function isMultipleSet<T>(s: SelectionSet<T>): s is SelectionSet<T> & { multiple: true } {
return (s as { multiple?: boolean }).multiple === true;
} Try / catch
try {
set.select(...values);
} catch (e) {
if ((e as Error).message.includes('not multiple selection')) {
values.forEach(v => set.select(v)); // degrade to sequential
} else throw e;
} Prevention
- Always pass { multiple: true } when any call site may pass more than one item.
- Type helpers to accept a single SelectableWithIndex unless the set is multiple.
- Run dev builds in CI — ngDevMode assertions surface this early.
When it happens
Trigger: Calling selectionSet.select(itemA, itemB) (spread of an array, or literal multiple args) on a SelectionSet constructed without multiple: true. Deselect/isSelected with one arg is fine; only select with >1 args on a non-multiple set throws.
Common situations: Refactoring code that used SelectionModel multiple mode to SelectionSet; passing a user-selected array straight into select(...items) while forgetting the `multiple` constructor option; a shared helper that always spreads arrays.
Related errors
- SelectionSet: index required when trackByFn is used.
- CdkSelectAll: missing CdkSelection in the parent
- Unknown data source
- CdkSelection: index required when trackBy is used
- CdkSelection: multiple selection not enabled
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/daf62287c112f052.
Report an issue: GitHub.