{"record":{"id":"ffb3226b717b62ad","repo":"angular/components","slug":"cannot-retrieve-popup-content-because-the-combobox","errorCode":null,"errorMessage":"Cannot retrieve popup content because the combobox is closed or not associated with a popup controls ID.","messagePattern":"Cannot retrieve popup content because the combobox is closed or not associated with a popup controls ID\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/aria/combobox/testing/combobox-harness.ts","lineNumber":57,"sourceCode":"        async (harness, disabled) => (await harness.isDisabled()) === disabled,\n      );\n  }\n\n  /**\n   * Gets the component harness for the active widget contained inside the popup.\n   * Use this when you need to access the harness of the widget itself (e.g., `ListboxHarness`),\n   * rather than querying items within it.\n   * @param type The harness type to locate. Must implement standard static `.with()` method.\n   */\n  async getPopupWidget<T extends ComponentHarness>(\n    type: ComponentHarnessConstructor<T> & {\n      with: (options?: {selector?: string}) => HarnessPredicate<T>;\n    },\n  ): Promise<T> {\n    const host = await this.host();\n    const controlsId = await host.getAttribute('aria-controls');\n    if (!controlsId) {\n      throw new Error(\n        'Cannot retrieve popup content because the combobox is closed or not associated with a popup controls ID.',\n      );\n    }\n    return this.documentRootLocatorFactory().locatorFor(type.with({selector: `#${controlsId}`}))();\n  }\n\n  /**\n   * Gets a harness loader scoped to the content inside the popup container.\n   * Note that lookups performed by this loader will only find descendants of the popup container.\n   */\n  async getPopupLoader(): Promise<HarnessLoader> {\n    return this.getRootHarnessLoader();\n  }\n\n  /** Overrides root loader to automatically resolve queries nested inside the associated popup. */\n  protected override async getRootHarnessLoader(): Promise<HarnessLoader> {\n    const host = await this.host();\n    const controlsId = await host.getAttribute('aria-controls');","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/aria/combobox/testing/combobox-harness.ts#L39-L75","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst popup = await harness.getPopupWidget({selector: '.my-options'});\n// after\nawait harness.open();\nconst popup = await harness.getPopupWidget({selector: '.my-options'});","handlingStrategy":"validation","validationCode":"const host = await harness.host();\nif (!(await host.getAttribute('aria-controls'))) {\n  await harness.open(); // or fail fast\n}","typeGuard":"async function popupAvailable(harness: {host(): Promise<any>}): Promise<boolean> {\n  return !!(await (await harness.host()).getAttribute('aria-controls'));\n}","tryCatchPattern":"try {\n  const popup = await harness.getPopupWidget();\n} catch (e) {\n  if ((e as Error).message.includes('Cannot retrieve popup content')) {\n    await harness.open();\n  } else throw e;\n}","preventionTips":["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."],"tags":["angular","cdk-harness","testing","aria","combobox"],"backgroundTag":"harness-popup-not-open","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}