angular/components · error · Error
Cannot retrieve popup content because the combobox is closed
Error message
Cannot retrieve popup content because the combobox is closed or not associated with a popup controls ID.
What it means
The combobox harness's getPopupWidget method reads the host element's 'aria-controls' attribute to locate the popup widget element by ID. When the combobox is closed (or was never wired to a popup), no aria-controls is present, so the harness cannot resolve the popup element and throws this error instead of returning null.
Source
Thrown at src/aria/combobox/testing/combobox-harness.ts:57
async (harness, disabled) => (await harness.isDisabled()) === disabled,
);
}
/**
* Gets the component harness for the active widget contained inside the popup.
* Use this when you need to access the harness of the widget itself (e.g., `ListboxHarness`),
* rather than querying items within it.
* @param type The harness type to locate. Must implement standard static `.with()` method.
*/
async getPopupWidget<T extends ComponentHarness>(
type: ComponentHarnessConstructor<T> & {
with: (options?: {selector?: string}) => HarnessPredicate<T>;
},
): Promise<T> {
const host = await this.host();
const controlsId = await host.getAttribute('aria-controls');
if (!controlsId) {
throw new Error(
'Cannot retrieve popup content because the combobox is closed or not associated with a popup controls ID.',
);
}
return this.documentRootLocatorFactory().locatorFor(type.with({selector: `#${controlsId}`}))();
}
/**
* Gets a harness loader scoped to the content inside the popup container.
* Note that lookups performed by this loader will only find descendants of the popup container.
*/
async getPopupLoader(): Promise<HarnessLoader> {
return this.getRootHarnessLoader();
}
/** Overrides root loader to automatically resolve queries nested inside the associated popup. */
protected override async getRootHarnessLoader(): Promise<HarnessLoader> {
const host = await this.host();
const controlsId = await host.getAttribute('aria-controls');View on GitHub (pinned to 0411926e7d)
Solutions
- Open the combobox before querying the popup (e.g. await harness.open() or dispatch interaction on the trigger) so aria-controls is set.
- Verify the combobox component sets aria-controls on its host pointing at the popup element's ID.
- Await open state: check await harness.isOpen() before calling getPopupWidget.
- If using a custom combobox, ensure ngComboboxWidget assigns the popup an ID and links it via aria-controls.
Example fix
// before
const popup = await harness.getPopupWidget({selector: '.my-options'});
// after
await harness.open();
const popup = await harness.getPopupWidget({selector: '.my-options'}); Defensive patterns
Strategy: validation
Validate before calling
const host = await harness.host();
if (!(await host.getAttribute('aria-controls'))) {
await harness.open(); // or fail fast
} Type guard
async function popupAvailable(harness: {host(): Promise<any>}): Promise<boolean> {
return !!(await (await harness.host()).getAttribute('aria-controls'));
} Try / catch
try {
const popup = await harness.getPopupWidget();
} catch (e) {
if ((e as Error).message.includes('Cannot retrieve popup content')) {
await harness.open();
} else throw e;
} Prevention
- Always open the combobox before querying popup content in tests.
- Assert aria-controls is set as part of your combobox component's unit tests.
- Use a helper that opens-then-queries instead of calling getPopupWidget directly.
When it happens
Trigger: Calling harness.getPopupWidget(...) (or getPopupLoader/getRootHarnessLoader) while the combobox popup is closed, or on a custom combobox whose host element never sets aria-controls to the popup's ID.
Common situations: Tests that query popup options without first opening the combobox (e.g. missing an open()/click on the trigger); custom combobox implementations that omit the aria-controls wiring the Angular ARIA combobox pattern requires; popup unmounted after close so the attribute is removed.
Related errors
- Could not find tab matching filters: ${JSON.stringify(filter
- Cannot find calendar cell matching filter ${JSON.stringify(f
- Element is not associated with a calendar
- Cannot read "${filePath}" because it does not exist.
- Unable to retrieve options for autocomplete. Autocomplete pa
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/ffb3226b717b62ad.
Report an issue: GitHub.