grafana/k6 · error

parsing selector %q: %w

Error message

parsing selector %q: %w

What it means

ElementHandle.Query() rejects the selector before touching the page: NewSelector (selectors.go:49) failed to parse it. Concrete parse failures: an empty selector string, more than one '*' capture prefix in a '>>' chain ('only one of the selectors can capture using * modifier'), or a part whose engine prefix is not a supported query engine.

Source

Thrown at internal/js/modules/k6/browser/common/element_handle.go:1192

	}
	pressAction := h.newAction(
		[]string{}, press, false, withRetry, opts.NoWaitAfter, opts.Timeout,
	)
	if _, err := call(h.ctx, pressAction, opts.Timeout); err != nil {
		return fmt.Errorf("pressing %q on element: %w", key, err)
	}

	applySlowMo(h.ctx)

	return nil
}

// Query runs "element.querySelector" within the page. If no element matches the selector,
// the return value resolves to "null".
func (h *ElementHandle) Query(selector string, strict bool) (_ *ElementHandle, rerr error) {
	parsedSelector, err := NewSelector(selector)
	if err != nil {
		return nil, fmt.Errorf("parsing selector %q: %w", selector, err)
	}

	// Check for frame navigation in the selector
	frameNavIndex := h.findFrameNavigationIndex(parsedSelector)
	if frameNavIndex != -1 {
		// Strict is true because we assume the user is interested in the element
		// in the frame and not the frame it is in.
		opts := &FrameWaitForSelectorOptions{
			State:   DOMElementStateAttached,
			Timeout: h.frame.defaultTimeout(),
			Strict:  true,
		}

		frame, afterFrameSelector, err := h.stepIntoFrame(h.ctx, parsedSelector, frameNavIndex, opts)
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Log and assert the selector string is non-empty before use (especially dynamic ones)
  2. Use at most one '*' capture prefix in a chained selector
  3. Stick to supported engines: bare CSS, 'xpath=', 'text=', or recognized engine= prefixes
  4. Test the exact selector string in browser devtools / a minimal k6 script first

Example fix

// before
await page.$(`*css=tr >> *text=Delete`); // two captures -> parse error
// after
await page.$(`*css=tr >> text=Delete`); // single capture
Defensive patterns

Strategy: validation

Validate before calling

// Validate a k6 selector string before use
function checkSelector(s) {
  if (typeof s !== 'string' || s.trim() === '') throw new Error('selector is empty');
  const captures = (s.match(/(^|\s|>>)\*/g) || []).length;
  if (captures > 1) throw new Error('only one * capture allowed');
  return s;
}

Try / catch

try { await el.$(sel); }
catch (e) { if (/parsing selector/.test(e.message)) { /* fix sel, it never reached the page */ } throw e; }

Prevention

When it happens

Trigger: Calling $() with '' (often a dynamically built selector that evaluated to empty); using two captures like '*css=a >> *text=Login'; using an engine prefix k6 does not support (only css/xpath/text and the recognized engine names map); stray quotes in '>>' chains.

Common situations: Selectors interpolated from variables/CSV data that can be blank; Playwright selectors pasted in that rely on engines k6's parser doesn't recognize; copy-paste typos of the capture modifier.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/ad9d5dd3d4faa79f. Report an issue: GitHub.