angular/components · error

Index must not be negative

Error message

Index must not be negative

What it means

Thrown by ComponentHarnessEnvironment.getHarnessAtIndex when the caller passes a negative offset. The method indexes into the array of matched harnesses, and a negative index has no meaning there, so the library rejects it up-front before performing any locator queries.

Source

Thrown at src/cdk/testing/harness-environment.ts:266

    return this.locatorForOptional(query)();
  }

  /**
   * Searches for an instance of the component corresponding to the given harness type and index
   * under the `HarnessEnvironment`'s root element, and returns a `ComponentHarness` for that
   * instance. The index specifies the offset of the component to find. If no matching
   * component is found at that index, an error is thrown.
   * @param query A query for a harness to create
   * @param index The zero-indexed offset of the component to find
   * @return An instance of the given harness type
   * @throws If a matching component instance can't be found.
   */
  async getHarnessAtIndex<T extends ComponentHarness>(
    query: HarnessQuery<T>,
    offset: number,
  ): Promise<T> {
    if (offset < 0) {
      throw Error('Index must not be negative');
    }
    const harnesses = await this.locatorForAll(query)();
    if (offset >= harnesses.length) {
      throw Error(`No harness was located at index ${offset}`);
    }
    return harnesses[offset];
  }

  /**
   * Searches for all instances of the component corresponding to the given harness type under the
   * `HarnessEnvironment`'s root element, and returns a list `ComponentHarness` for each instance.
   * @param query A query for a harness to create
   * @return A list instances of the given harness type.
   */
  getAllHarnesses<T extends ComponentHarness>(query: HarnessQuery<T>): Promise<T[]> {
    return this.locatorForAll(query)();
  }

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Pass a non-negative, in-range offset; check it is >= 0 before calling.
  2. Use locatorForAll/queryAll and index the returned array yourself with bounds checking.
  3. If looking for the last harness, use harnesses[harnesses.length - 1] on results from getHarnesses, not a computed negative value.

Example fix

// before
const harness = await env.getHarnessAtIndex(MyHarness, selectedIndex);
// after
if (selectedIndex < 0) throw new Error('Nothing selected');
const harness = await env.getHarnessAtIndex(MyHarness, selectedIndex);
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(offset) || offset < 0) throw new RangeError(`offset must be >= 0, got ${offset}`);

Type guard

const isValidOffset = (n: unknown): n is number => typeof n === 'number' && Number.isInteger(n) && n >= 0;

Try / catch

try { return await env.getHarnessAtIndex(MyHarness, offset); } catch (e) { if ((e as Error).message.includes('Index must not be negative')) return null; throw e; }

Prevention

When it happens

Trigger: Calling getHarnessAtIndex(query, offset) with offset < 0, typically from a loop that computes the index dynamically (e.g. counter starting at -1, or index derived from an empty/decremented variable).

Common situations: Loop variables initialized wrong, off-by-one logic when picking 'the last but one' harness (index length-2 on small lists), or binding an index from user/model state that can be -1 (e.g. selectedIndex of an empty list).

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/7e52f7597f483b3a. Report an issue: GitHub.