tree-sitter/tree-sitter · error · Error

Pattern index is ${patternIndex} but the pattern count is ${

Error message

Pattern index is ${patternIndex} but the pattern count is ${this.predicates.length}

What it means

Plain Error thrown by Query.disablePattern(patternIndex) when patternIndex >= this.predicates.length (predicates is built per pattern in the constructor, so its length equals the query's pattern count). The guard bounds-checks the index before calling _ts_query_disable_pattern on the wasm side. Note the check only catches too-large indices — a negative patternIndex passes this guard.

Source

Thrown at lib/binding_web/src/query.ts:965

   */
  disableCapture(captureName: string): void {
    const captureNameLength = C.lengthBytesUTF8(captureName);
    const captureNameAddress = C._malloc(captureNameLength + 1);
    C.stringToUTF8(captureName, captureNameAddress, captureNameLength + 1);
    C._ts_query_disable_capture(this[0], captureNameAddress, captureNameLength);
    C._free(captureNameAddress);
  }

  /**
   * Disable a certain pattern within a query.
   *
   * This prevents the pattern from matching, and also avoids any resource
   * usage associated with the pattern. This throws an error if the pattern
   * index is out of bounds.
   */
  disablePattern(patternIndex: number): void {
    if (patternIndex >= this.predicates.length) {
      throw new Error(
        `Pattern index is ${patternIndex} but the pattern count is ${this.predicates.length}`
      );
    }
    C._ts_query_disable_pattern(this[0], patternIndex);
  }

  /**
   * Check if, on its last execution, this cursor exceeded its maximum number
   * of in-progress matches.
   */
  didExceedMatchLimit(): boolean {
    return this.exceededMatchLimit;
  }

  /** Get the byte offset where the given pattern starts in the query's source. */
  startIndexForPattern(patternIndex: number): number {
    if (patternIndex >= this.predicates.length) {
      throw new Error(

View on GitHub (pinned to dff1fd868c)

Solutions

  1. Check the bound first: if (patternIndex < query.patternCount()) query.disablePattern(patternIndex);
  2. Fix off-by-one loops to use i < query.patternCount(), not <=.
  3. Stop hard-coding pattern indices: look patterns up by behavior (predicatesForPattern) or re-derive indices after every change to the query source.
  4. Always call patternCount() on the same Query instance you are disabling on, at call time.

Example fix

// before
for (let i = 0; i <= query.patternCount(); i++) query.disablePattern(i); // last i throws

// after
for (let i = 0; i < query.patternCount(); i++) query.disablePattern(i);
Defensive patterns

Strategy: validation

Validate before calling

const count = query.patternCount();
if (!Number.isInteger(patternIndex) || patternIndex < 0 || patternIndex >= count) {
  throw new RangeError(`patternIndex must be in [0, ${count})`);
}
query.disablePattern(patternIndex);

Type guard

function isValidPatternIndex(query: Query, i: unknown): i is number {
  return Number.isInteger(i) && (i as number) >= 0 && (i as number) < query.patternCount();
}

Try / catch

try {
  query.disablePattern(patternIndex);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Pattern index is')) {
    console.warn(`Skipping disable: pattern ${patternIndex} does not exist (count ${query.patternCount()})`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling disablePattern(query.patternCount()) or higher (classic <= vs < loop bound); hard-coding an index (e.g. disablePattern(3)) and later editing the query source so it has fewer patterns; using a pattern index obtained from a different Query object; computing the bound from a stale patternCount captured before the query was rebuilt.

Common situations: Dynamic rule toggles in editor plugins (disable this highlight pattern) where the .scm file evolves between releases; loops written as for (let i = 0; i <= query.patternCount(); i++); mixing indices from match results of one query with a second, smaller query.

Related errors


AI-assisted analysis of tree-sitter/tree-sitter@dff1fd868c (2026-08-16). Data as JSON: /api/errors/877de9aeba5880f2. Report an issue: GitHub.