grafana/k6 · error

"name" attribute must be a string or a regular expression

Error message

"name" attribute must be a string or a regular expression

What it means

After a successful innerText evaluation (frame.go:1353), k6 type-asserts the returned CDP value to string and errors with 'unexpected type %T' when it is not. innerText is spec-defined to return a string, so this fires only when the page returns something abnormal: an overridden innerText getter on the prototype chain, or a DevTools protocol conversion edge case. Treat it as a signal of page tampering or a browser-module bug, not a selector problem.

Source

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

        validateSupportedRole(attr.name, kAriaLevelRoles, role);
        if (typeof attr.value === "string")
          attr.value = +attr.value;
        if (attr.op !== "=" || typeof attr.value !== "number" || Number.isNaN(attr.value))
          throw new Error(`"level" attribute must be compared to a number`);
        options.level = attr.value;
        break;
      }
      case "disabled": {
        validateSupportedValues(attr, [true, false]);
        validateSupportedOp(attr, ["<truthy>", "="]);
        options.disabled = attr.op === "<truthy>" ? true : attr.value;
        break;
      }
      case "name": {
        if (attr.op === "<truthy>")
          throw new Error(`"name" attribute must have a value`);
        if (typeof attr.value !== "string" && !(attr.value instanceof RegExp))
          throw new Error(`"name" attribute must be a string or a regular expression`);
        options.name = attr.value;
        options.nameOp = attr.op;
        options.exact = attr.caseSensitive;
        break;
      }
      case "include-hidden": {
        validateSupportedValues(attr, [true, false]);
        validateSupportedOp(attr, ["<truthy>", "="]);
        options.includeHidden = attr.op === "<truthy>" ? true : attr.value;
        break;
      }
      default: {
        throw new Error(`Unknown attribute "${attr.name}", must be one of ${kSupportedAttributes.map((a) => `"${a}"`).join(", ")}.`);
      }
    }
  }
  return options;
}

View on GitHub (pinned to 01ffac6f24)

Solutions

  1. Check the real value type via evaluation: const v = await page.evaluate(`document.querySelector(sel).innerText`); inspect typeof v.
  2. Fall back to textContent through page.evaluate when innerText is patched.
  3. Report to grafana/k6 with a repro if the raw getter returns a string but the error persists.
  4. Pin a standard Chromium executable for consistent protocol behavior.

Example fix

// before
const txt = await page.innerText('#msg'); // unexpected type ...

// after
const txt = await page.evaluate(`document.querySelector('#msg').innerText`);
if (typeof txt !== 'string') throw new Error('innerText getter patched');
Defensive patterns

Strategy: fallback

Validate before calling

const t = await page.evaluate(`
  (() => { const el = document.querySelector('#msg'); return el ? typeof el.innerText : 'no-el'; })()
`);
if (t !== 'string') throw new Error('innerText getter patched');

Type guard

function isTextString(v) { return typeof v === 'string'; }

Try / catch

try {
  return await page.innerText(sel);
} catch (e) {
  if (String(e).includes('unexpected type')) {
    return await page.evaluate(`document.querySelector('${sel}').innerText`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Page code overrides HTMLElement.prototype.innerText to return objects/numbers/undefined; bot-mitigation scripts poison DOM accessors; CDP RemoteObject conversion returns a non-string for the getter; Chromium/k6 browser module version drift.

Common situations: Testing heavily protected sites; custom elements frameworks replacing text accessors; embedded/legacy Chromium builds.

Related errors


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