angular/components · error · Error
ListKeyManager items in typeahead mode must implement the `g
Error message
ListKeyManager items in typeahead mode must implement the `getLabel` method.
What it means
ListKeyManager.withTypeAhead needs to read the text label of each item to match keystrokes; therefore every item in the QueryList must implement getLabel(): string. withTypeAhead throws this dev-mode error if any item lacks a getLabel function (when the list is non-empty).
Source
Thrown at src/cdk/a11y/key-manager/list-key-manager.ts:148
/**
* Modifier keys which are allowed to be held down and whose default actions will be prevented
* as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
*/
withAllowedModifierKeys(keys: ListKeyManagerModifierKey[]): this {
this._allowedModifierKeys = keys;
return this;
}
/**
* Turns on typeahead mode which allows users to set the active item by typing.
* @param debounceInterval Time to wait after the last keystroke before setting the active item.
*/
withTypeAhead(debounceInterval: number = 200): this {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const items = this._getItemsArray();
if (items.length > 0 && items.some(item => typeof item.getLabel !== 'function')) {
throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
}
}
this._typeaheadSubscription.unsubscribe();
const items = this._getItemsArray();
this._typeahead = new Typeahead(items, {
debounceInterval: typeof debounceInterval === 'number' ? debounceInterval : undefined,
skipPredicate: item => this._skipPredicateFn(item),
});
this._typeaheadSubscription = this._typeahead.selectedItem.subscribe(item => {
this.setActiveItem(item);
});
return this;
}
View on GitHub (pinned to 0411926e7d)
Solutions
- Implement getLabel(): string on every item directive/component managed by the key manager.
- Create a shared interface (e.g., interface WithLabel { getLabel(): string }) and have all items implement it.
- Remove withTypeAhead() if keyboard typeahead is not needed.
Example fix
// before
export class MyOption { constructor(public value: string) {} }
// after
export class MyOption { constructor(public value: string) {} }
getLabel(): string { return this.value; } Defensive patterns
Strategy: type-guard
Validate before calling
interface LabelItem { getLabel(): string; }
function allItemsHaveLabel(items: unknown[]): items is LabelItem[] {
return items.every(i => typeof (i as LabelItem).getLabel === 'function');
}
if (allItemsHaveLabel(options.toArray())) keyManager.withTypeAhead(); Type guard
function implementsGetLabel(item: unknown): item is { getLabel(): string } {
return typeof (item as { getLabel?: unknown }).getLabel === 'function';
} Try / catch
try {
keyManager.withTypeAhead();
} catch (e) {
if ((e as Error).message.includes('getLabel')) {
console.error('Items must implement getLabel for typeahead');
} else throw e;
} Prevention
- Define a shared interface with getLabel(): string that every managed item directive implements.
- Write a test asserting typeof item.getLabel === 'function' for each item type.
- Skip withTypeAhead() when items cannot provide labels.
When it happens
Trigger: Calling keyManager.withTypeAhead() where the managed QueryList contains directive/component instances that do not define getLabel(); adding a new item type to the list that was not updated for typeahead; passing a generic ListKeyManager over plain objects.
Common situations: Mixing item classes in a listbox/menu; upgrading CDK and enabling typeahead on an existing key manager; implementing a custom option directive modeled after an older API without getLabel.
Related errors
- KeyManager items in typeahead mode must implement the `getLa
- ListKeyManager constructed with a signal must receive an inj
- SelectionSet: not multiple selection
- SelectionSet: index required when trackByFn is used.
- CdkSelectAll: missing CdkSelection in the parent
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/5d8174ba35ba5cbc.
Report an issue: GitHub.