tree-sitter/tree-sitter · error · Error
Arguments must be numbers
Error message
Arguments must be numbers
What it means
Plain Error thrown by Query.matches() in the web binding. After destructuring the options object, the only argument type actually enforced is matchLimit: if options.matchLimit was supplied and typeof matchLimit !== 'number', it throws 'Arguments must be numbers' before touching the wasm cursor. Note the misleading breadth of the message — only matchLimit is checked here, and NaN passes because typeof NaN === 'number'.
Source
Thrown at lib/binding_web/src/query.ts:734
*/
matches(
node: Node,
options: QueryOptions = {}
): QueryMatch[] {
const startPosition = options.startPosition ?? ZERO_POINT;
const endPosition = options.endPosition ?? ZERO_POINT;
const startIndex = options.startIndex ?? 0;
const endIndex = options.endIndex ?? 0;
const startContainingPosition = options.startContainingPosition ?? ZERO_POINT;
const endContainingPosition = options.endContainingPosition ?? ZERO_POINT;
const startContainingIndex = options.startContainingIndex ?? 0;
const endContainingIndex = options.endContainingIndex ?? 0;
const matchLimit = options.matchLimit ?? 0xFFFFFFFF;
const maxStartDepth = options.maxStartDepth ?? 0xFFFFFFFF;
const progressCallback = options.progressCallback;
if (typeof matchLimit !== 'number') {
throw new Error('Arguments must be numbers');
}
this.matchLimit = matchLimit;
if (endIndex !== 0 && startIndex > endIndex) {
throw new Error('`startIndex` cannot be greater than `endIndex`');
}
if (endPosition !== ZERO_POINT && (
startPosition.row > endPosition.row ||
(startPosition.row === endPosition.row && startPosition.column > endPosition.column)
)) {
throw new Error('`startPosition` cannot be greater than `endPosition`');
}
if (endContainingIndex !== 0 && startContainingIndex > endContainingIndex) {
throw new Error('`startContainingIndex` cannot be greater than `endContainingIndex`');
}
View on GitHub (pinned to dff1fd868c)
Solutions
- Coerce the value before the call: matchLimit: Number(options.matchLimit) — or fix the source so a real number is passed.
- If the value comes from env/config, parse once at load time (parseInt/Number) and validate with Number.isFinite.
- Enable TypeScript and type the options argument as QueryOptions so string/BigInt mismatches are compile-time errors.
- Remember NaN is not caught by this check — guard Number.isFinite(matchLimit) yourself.
Example fix
// before
const limit = params.get('matchLimit'); // "5000" (string)
const matches = query.matches(node, { matchLimit: limit }); // throws
// after
const limit = Number(params.get('matchLimit'));
const matches = query.matches(node, { matchLimit: Number.isFinite(limit) ? limit : undefined }); Defensive patterns
Strategy: type-guard
Validate before calling
const limit = options.matchLimit;
if (limit !== undefined && (typeof limit !== 'number' || !Number.isFinite(limit))) {
throw new TypeError(`matchLimit must be a finite number, got ${typeof limit}`);
}
const matches = query.matches(node, options); Type guard
function isFiniteNumber(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v);
}
// usage
if (isFiniteNumber(opts.matchLimit)) query.matches(node, opts);
else query.matches(node, { ...opts, matchLimit: Number(opts.matchLimit) || undefined }); Try / catch
try {
const matches = query.matches(node, options);
} catch (e) {
if (e instanceof Error && e.message === 'Arguments must be numbers') {
options = { ...options, matchLimit: Number(options.matchLimit) };
matches = query.matches(node, options); // retry with coerced value
} else throw e;
} Prevention
- Coerce config/env/URL-sourced numbers once at load time with Number() and reject non-finite results.
- Type the options argument as QueryOptions so TypeScript catches strings at compile time.
- Remember the runtime check accepts NaN — validate Number.isFinite yourself.
- Don't ship raw strings into query options via spread from JSON payloads.
When it happens
Trigger: Calling query.matches(node, { matchLimit: '1000' }) with a string; matchLimit coming from URLSearchParams, localStorage, process.env, or a JSON config file (all yield strings); passing a BigInt (typeof 'bigint'); passing an options object typed as any in JavaScript so the mistake is not caught at compile time.
Common situations: Reading matchLimit/maxStartDepth from user configuration (editor settings, query URLs) without coercing to Number; JS projects without TypeScript checking where a string slips in; migrating code from the node binding (which validates differently) to the web binding.
Related errors
- Grammar's 'conflicts' property must be a function.
- Grammar's 'inline' property must be a function.
- Grammar's 'supertypes' property must be a function.
- Grammar's 'precedences' property must be a function
- Argument must be a Language
AI-assisted analysis of tree-sitter/tree-sitter@dff1fd868c (2026-08-16).
Data as JSON: /api/errors/267c06ed5204f581.
Report an issue: GitHub.