puppeteer/puppeteer · error · Error
At least one query method must be defined.
Error message
At least one query method must be defined.
What it means
CustomQuerySelectorRegistry.register requires a handler that defines at least one of queryOne or queryAll (it can derive the other). The final else-if catches the case where BOTH are missing/undefined and rejects the registration. This guards Puppeteer.registerCustomQueryHandler against useless handlers.
Source
Thrown at packages/puppeteer-core/src/injected/CustomQuerySelector.ts:41
#selectors = new Map<string, CustomQuerySelector>();
register(name: string, handler: CustomQueryHandler): void {
if (!handler.queryOne && handler.queryAll) {
const querySelectorAll = handler.queryAll;
handler.queryOne = (node, selector) => {
for (const result of querySelectorAll(node, selector)) {
return result;
}
return null;
};
} else if (handler.queryOne && !handler.queryAll) {
const querySelector = handler.queryOne;
handler.queryAll = (node, selector) => {
const result = querySelector(node, selector);
return result ? [result] : [];
};
} else if (!handler.queryOne || !handler.queryAll) {
throw new Error('At least one query method must be defined.');
}
this.#selectors.set(name, {
querySelector: handler.queryOne,
querySelectorAll: handler.queryAll!,
});
}
unregister(name: string): void {
this.#selectors.delete(name);
}
get(name: string): CustomQuerySelector | undefined {
return this.#selectors.get(name);
}
clear(): void {
this.#selectors.clear();View on GitHub (pinned to d484e21c17)
Solutions
- Provide at least queryOne or queryAll in the handler passed to registerCustomQueryHandler.
- Double-check method names are exactly 'queryOne' and 'queryAll'.
- If you only have a multi-result query, register queryAll and Puppeteer will synthesize queryOne (and vice-versa).
- Add a compile-time type annotation (: CustomQueryHandler) to catch missing methods at build time.
Example fix
// before
Puppeteer.registerCustomQueryHandler('foo', {});
// after
Puppeteer.registerCustomQueryHandler('foo', {
queryAll: (node, selector) => node.querySelectorAll(selector),
}); Defensive patterns
Strategy: validation
Validate before calling
function registerSafe(name: string, handler: Record<string, unknown>) {
if (typeof handler.queryOne !== 'function' && typeof handler.queryAll !== 'function') {
throw new Error(`Cannot register '${name}': provide queryOne and/or queryAll`);
}
Puppeteer.registerCustomQueryHandler(name, handler as any);
} Type guard
const isValidHandler = (h: unknown): boolean =>
!!h && (typeof (h as any).queryOne === 'function' ||
typeof (h as any).queryAll === 'function'); Try / catch
try {
Puppeteer.registerCustomQueryHandler('name', handler);
} catch (e) {
if (e instanceof Error && e.message === 'At least one query method must be defined.') {
// handler missing methods — log and skip registration
}
throw e;
} Prevention
- Annotate handlers with the CustomQueryHandler type to catch missing methods at build time.
- Double-check method names are exactly queryOne/queryAll.
- Register only one of the two if you have a single-result or multi-result implementation.
When it happens
Trigger: Calling Puppeteer.registerCustomQueryHandler('name', {}) with an empty handler object, or with a handler whose queryOne and queryAll are both undefined (e.g. a typo in the method name).
Common situations: Typos like { queyOne: ... } (misspelled); passing a class instance that doesn't expose the expected methods; spreading a config that omits both keys.
Related errors
- Unknown selector type: ${selector.name}
- Multiple deep combinators found in sequence.
- Unsupported browser '${browser.name}'
- Unsupported platform '${platform}'
- No pinned version found for ${browserName}
AI-assisted analysis of puppeteer/puppeteer@d484e21c17 (2026-08-12).
Data as JSON: /api/errors/3fb91688761b066b.
Report an issue: GitHub.