microsoft/playwright · error · Error

url parameter should be string, RegExp, URLPattern or functi

Error message

url parameter should be string, RegExp, URLPattern or function

What it means

Thrown by urlMatches when the `match` argument is not a string, RegExp, URLPattern, or function. After all type checks (isString, isRegExp, isURLPattern, typeof function) fail, the value is of an unsupported type and cannot be used for URL matching.

Source

Thrown at packages/isomorphic/urlMatch.ts:193

  return match1 === match2;
}

export function urlMatches(baseURL: string | undefined, urlString: string, match: URLMatch | undefined, webSocketUrl?: boolean): boolean {
  if (match === undefined || match === '')
    return true;
  if (isString(match))
    match = new RegExp(resolveGlobToRegexPattern(baseURL, match, webSocketUrl));
  if (isRegExp(match)) {
    match.lastIndex = 0;
    return match.test(urlString);
  }
  const url = parseURL(urlString);
  if (!url)
    return false;
  if (isURLPattern(match))
    return match.test(url.href);
  if (typeof match !== 'function')
    throw new Error('url parameter should be string, RegExp, URLPattern or function');
  return match(url);
}

export function resolveGlobToRegexPattern(baseURL: string | undefined, glob: string, webSocketUrl?: boolean): string {
  if (webSocketUrl)
    baseURL = toWebSocketBaseUrl(baseURL);
  glob = resolveGlobBase(baseURL, glob);
  return globToRegexPattern(glob);
}

function toWebSocketBaseUrl(baseURL: string | undefined) {
  // Allow http(s) baseURL to match ws(s) urls. Schemes are case-insensitive,
  // same as elsewhere in this file, so 'HTTP://...' should be rewritten too.
  if (baseURL && /^https?:\/\//i.test(baseURL))
    baseURL = baseURL.replace(/^https?/i, scheme => scheme.toLowerCase() === 'https' ? 'wss' : 'ws');
  return baseURL;
}

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Pass a glob string, RegExp, URLPattern instance, or a `(url: URL) => boolean` function.
  2. If using an object, construct a real `new URLPattern({...})` first.
  3. Wrap multi-match logic in a function that ORs individual checks.

Example fix

// before
page.route({ pathname: '/api' }, handler);  // plain object, not URLPattern

// after
page.route(new URLPattern({ pathname: '/api' }), handler);
// or simply
page.route('**/api', handler);
Defensive patterns

Strategy: type-guard

Validate before calling

function assertUrlMatch(m: unknown) {
  if (m === undefined || m === '') return;
  if (typeof m === 'string' || m instanceof RegExp || typeof m === 'function') return;
  if (typeof globalThis.URLPattern === 'function' && m instanceof globalThis.URLPattern) return;
  throw new Error('url match must be string | RegExp | URLPattern | function');
}

Type guard

import { isURLPattern } from 'playwright-core/lib/utils';
function isUrlMatch(m: unknown): m is string | RegExp | URLPattern | ((u: URL) => boolean) {
  return typeof m === 'string'
    || m instanceof RegExp
    || typeof m === 'function'
    || isURLPattern(m);
}

Try / catch

try {
  page.route(matcher as any, handler);
} catch (e) {
  if (/url parameter should be string/.test(e.message)) {
    throw new TypeError(`Invalid route matcher ${typeof matcher}; wrap object in new URLPattern()`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing an object, number, null (non-undefined), array, or any non-supported type as a URL match: `page.route(123, ...)`, `page.waitForRequest({ host: 'x' }, ...)` (plain object that is not a URLPattern), or `context.route(['a','b'], ...)`. Note `undefined`/'' short-circuit to match-all and do not throw.

Common situations: Passing a plain object literal expecting it to behave like URLPattern; using an array of matchers where a single matcher is required; type coercion bug feeding a number into a route matcher; URLPattern unavailable in the runtime so a value fails isURLPattern.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/4b9e7476c83ee7cc. Report an issue: GitHub.