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
- Check the bound first: if (patternIndex < query.patternCount()) query.disablePattern(patternIndex);
- Fix off-by-one loops to use i < query.patternCount(), not <=.
- Stop hard-coding pattern indices: look patterns up by behavior (predicatesForPattern) or re-derive indices after every change to the query source.
- 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
- Bound-check against query.patternCount() at call time, on the same Query instance.
- Use strict < in loops over pattern indices.
- Never hard-code pattern indices; re-derive them after editing the query source.
- Remember the library check misses negative indices — validate >= 0 yourself.
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
- QueryErrorKind.Syntax
- QueryErrorKind.NodeName
- QueryErrorKind.FieldName
- QueryErrorKind.CaptureName
- QueryErrorKind.PatternStructure
AI-assisted analysis of tree-sitter/tree-sitter@dff1fd868c (2026-08-16).
Data as JSON: /api/errors/877de9aeba5880f2.
Report an issue: GitHub.