grafana/k6 · error

evaluating pattern

Error message

evaluating pattern: %w

What it means

Produced by newRegExMatcher (browser/helpers.go:80): it builds the snippet `pattern + ".test('" + str + "')"` and runs it on the sobek runtime, wrapping any failure as 'evaluating pattern'. This matcher backs URL/pattern matching in page.waitForURL, page/frame.waitForNavigation({ url }), page.waitForRequest, page.waitForResponse and page.route. Quoted-string patterns are compared literally and never reach the regex engine; everything else is executed as an ECMAScript regex source, so an invalid regex (unbalanced parens/brackets) or a URL containing an apostrophe breaks the generated expression.

Solutions

  1. Pass a real RegExp object instead of a glob string: page.waitForURL(/\/q='k6'/)
  2. Escape regex metacharacters in dynamic patterns before passing them
  3. Avoid patterns and expected URLs containing single quotes, or match on a quote-free substring
  4. Pre-validate the pattern in JS with new RegExp(...) before the call

Example fix

// before
page.waitForURL("**/results?q='k6'"); // apostrophes/glob break the generated regex
// after
page.waitForURL(/\/results\?q='k6'/);
Defensive patterns

Strategy: validation

Validate before calling

function assertValidPattern(p) {
  if (typeof p === 'string') { new RegExp(p); return; } // throws SyntaxError if invalid
  if (p instanceof RegExp) return;
  throw new Error('pattern must be a string or RegExp');
}
assertValidPattern(pattern); // before waitForURL/waitForNavigation/route
// avoid single quotes in matched URLs; match on a quote-free substring instead

Type guard

function isUsablePattern(p) {
  if (p instanceof RegExp) return true;
  if (typeof p !== 'string') return false;
  if (p.includes("'")) return false;
  try { new RegExp(p); return true; } catch { return false; }
}

Try / catch

try { await page.waitForURL(pattern, { timeout: 5000 }); } catch (e) { if (!String(e.message).includes('evaluating pattern')) throw e; /* fall back to an exact quoted URL */ }

Prevention

When it happens

Trigger: page.waitForURL("**/it's-done") — the apostrophe in the matched URL terminates the string literal in the generated snippet; page.route('api(v1', handler) — invalid regex source; passing glob strings containing (, [ or quotes where a RegExp is expected; page.waitForRequest("/search?q='k6'").

Common situations: Using Playwright glob patterns verbatim (k6 evaluates many of them as raw regex sources); localizing tests against URLs with apostrophes (Italian/French pages); patterns built by string concatenation that forget regex escaping.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/34024e37cad3eadb. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/helpers.go:80

	return args
}

// sobekEmptyString returns true if a given value is not nil or an empty string.
func sobekEmptyString(v sobek.Value) bool {
	return k6common.IsNullish(v) || strings.TrimSpace(v.String()) == ""
}

// newRegExMatcher returns a function that runs in the JS runtime's event loop
// for pattern matching. It uses ECMAScript RegEx engine for consistency.
//
// It's safe to call this function off of the event loop since the returned
// function gets run in the task queue, ensuring it runs on the event loop.
func newRegExMatcher(ctx context.Context, vu moduleVU, tq *taskqueue.TaskQueue) common.RegExMatcher {
	return func(pattern, str string) (bool, error) {
		return queueTask(ctx, tq, func() (bool, error) {
			v, err := vu.Runtime().RunString(pattern + `.test('` + str + `')`)
			if err != nil {
				return false, fmt.Errorf("evaluating pattern: %w", err)
			}
			return v.ToBoolean(), nil
		})()
	}
}

// promise runs fn in a goroutine and returns a new sobek.Promise.
//   - If fn returns a nil error, resolves the promise with the
//     first result value fn returns.
//   - Otherwise, rejects the promise with the error fn returns.
func promise(vu moduleVU, fn func() (result any, reason error)) *sobek.Promise {
	p, resolve, reject := promises.New(vu)
	go func() {
		v, err := fn()
		if err != nil {
			reject(k6ext.BrowserError(err))
			return
		}

View on GitHub (pinned to 01ffac6f24)