grafana/k6 · error

"${attr.name}" does not support "${attr.op}" matcher

Error message

"${attr.name}" does not support "${attr.op}" matcher

What it means

Frame.InnerHTML() (frame.go:1294) wraps failures of the innerHTML action with 'getting inner HTML of %q'. The action waits for a selector match in the attached state within Timeout and evaluates element.innerHTML in the page. Wrapped causes are selector timeouts, strict-mode violations, frame/context destruction during evaluation, or page-side exceptions thrown by overridden innerHTML getters.

Source

Thrown at internal/js/modules/k6/browser/common/js/injected_script.js:1158

  if (!result.name && !result.attributes.length)
    throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - selector cannot be empty`);
  return result;
}

// packages/injected/src/roleSelectorEngine.ts
var kSupportedAttributes = ["selected", "checked", "pressed", "expanded", "level", "disabled", "name", "include-hidden"];
kSupportedAttributes.sort();
function validateSupportedRole(attr, roles, role) {
  if (!roles.includes(role))
    throw new Error(`"${attr}" attribute is only supported for roles: ${roles.slice().sort().map((role2) => `"${role2}"`).join(", ")}`);
}
function validateSupportedValues(attr, values) {
  if (attr.op !== "<truthy>" && !values.includes(attr.value))
    throw new Error(`"${attr.name}" must be one of ${values.map((v) => JSON.stringify(v)).join(", ")}`);
}
function validateSupportedOp(attr, ops) {
  if (!ops.includes(attr.op))
    throw new Error(`"${attr.name}" does not support "${attr.op}" matcher`);
}
function validateAttributes(attrs, role) {
  const options = { role };
  for (const attr of attrs) {
    switch (attr.name) {
      case "checked": {
        validateSupportedRole(attr.name, kAriaCheckedRoles, role);
        validateSupportedValues(attr, [true, false, "mixed"]);
        validateSupportedOp(attr, ["<truthy>", "="]);
        options.checked = attr.op === "<truthy>" ? true : attr.value;
        break;
      }
      case "pressed": {
        validateSupportedRole(attr.name, kAriaPressedRoles, role);
        validateSupportedValues(attr, [true, false, "mixed"]);
        validateSupportedOp(attr, ["<truthy>", "="]);
        options.pressed = attr.op === "<truthy>" ? true : attr.value;
        break;

View on GitHub (pinned to 01ffac6f24)

Solutions

  1. Wait for the element before reading: await page.waitForSelector(sel, { timeout: 10000 }).
  2. Target the correct frame object for iframe content.
  3. Use a unique selector or locator API to avoid strict-mode ambiguity.
  4. Increase Timeout for slow-rendering apps: page.innerHTML(sel, { timeout: 60000 }).

Example fix

// before
const html = await page.innerHTML('#results');

// after
await page.waitForSelector('#results', { state: 'attached', timeout: 10000 });
const html = await page.innerHTML('#results');
Defensive patterns

Strategy: try-catch

Validate before calling

await page.waitForSelector('#results', { state: 'attached', timeout: 5000 });

Try / catch

try {
  return await page.innerHTML(sel, { timeout: 10000 });
} catch (e) {
  if (String(e).startsWith('getting inner HTML')) return ''; // element not there yet
  throw e;
}

Prevention

When it happens

Trigger: Selector matches nothing before Timeout; Strict:true and multiple elements match; iframe navigates while the value is being read; page scripts define a throwing innerText/innerHTML getter on the prototype.

Common situations: Scraping markup of lazily rendered widgets before they mount; reading innerHTML right after actions that trigger rerenders/navigation; querying the main frame for elements that live in an iframe.

Related errors


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