angular/components · error
CDK Component harness query must contain at least one elemen
Error message
CDK Component harness query must contain at least one element.
What it means
Thrown by _getAllHarnessesAndTestElements, the shared implementation behind locatorFor, locatorForOptional, and locatorForAll, when the queries array is empty. A locator must be built from at least one harness or element query; an empty query list is always a caller bug.
Source
Thrown at src/cdk/testing/harness-environment.ts:377
protected abstract createTestElement(element: E): TestElement;
/** Creates a `HarnessEnvironment` rooted at the given raw element. */
protected abstract createEnvironment(element: E): HarnessEnvironment<E>;
/**
* Gets a list of all elements matching the given selector under this environment's root element.
*/
protected abstract getAllRawElements(selector: string): Promise<E[]>;
/**
* Matches the given raw elements with the given list of element and harness queries to produce a
* list of matched harnesses and test elements.
*/
private async _getAllHarnessesAndTestElements<T extends (HarnessQuery<any> | string)[]>(
queries: T,
): Promise<LocatorFnResult<T>[]> {
if (!queries.length) {
throw Error('CDK Component harness query must contain at least one element.');
}
const {allQueries, harnessQueries, elementQueries, harnessTypes} = _parseQueries(queries);
// Combine all of the queries into one large comma-delimited selector and use it to get all raw
// elements matching any of the individual queries.
const rawElements = await this.getAllRawElements(
[...elementQueries, ...harnessQueries.map(predicate => predicate.getSelector())].join(','),
);
// If every query is searching for the same harness subclass, we know every result corresponds
// to an instance of that subclass. Likewise, if every query is for a `TestElement`, we know
// every result corresponds to a `TestElement`. Otherwise we need to verify which result was
// found by which selector so it can be matched to the appropriate instance.
const skipSelectorCheck =
(elementQueries.length === 0 && harnessTypes.size === 1) || harnessQueries.length === 0;
const perElementMatches = await parallel(() =>View on GitHub (pinned to 0411926e7d)
Solutions
- Pass at least one harness or selector query to the locator factory.
- Guard programmatic call sites: only create the locator when queries.length > 0.
- Provide a fallback query (e.g. a selector string) when the primary list may be empty.
Example fix
// before const q = shouldInclude ? [ChildHarness] : []; const lf = loader.locatorFor(...q); // after const q = shouldInclude ? [ChildHarness] : [FallbackHarness]; const lf = loader.locatorFor(...q);
Defensive patterns
Strategy: validation
Validate before calling
if (!queries.length) throw new Error('locator requires at least one query');
const lf = loader.locatorFor(...queries); Type guard
const hasQueries = <T>(q: T[]): q is [T, ...T[]] => q.length > 0;
Try / catch
try { return await loader.locatorFor(...queries)(); } catch (e) { if ((e as Error).message.includes('must contain at least one element')) throw new Error('Empty harness query list', {cause: e}); throw e; } Prevention
- Never spread possibly-empty arrays into locatorFor* without a guard
- Provide default/fallback queries when building lists conditionally
When it happens
Trigger: Calling loader.locatorFor() / locatorForOptional() / locatorForAll() with no arguments, or spreading a conditionally-built array of queries that ended up empty.
Common situations: Programmatic query building: const queries = shouldInclude ? [ChildHarness] : []; then locatorFor(...queries) with the flag false; also hardcoded locatorFor() calls after refactoring away the only query.
Related errors
- Index must not be negative
- No harness was located at index ${offset}
- Failed to find element matching one of the following queries
- Unable to retrieve options for autocomplete. Autocomplete pa
- Unable to retrieve option groups for autocomplete. Autocompl
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/ed382789220ab7c9.
Report an issue: GitHub.