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
- Check the real value type via evaluation: const v = await page.evaluate(`document.querySelector(sel).innerText`); inspect typeof v.
- Fall back to textContent through page.evaluate when innerText is patched.
- Report to grafana/k6 with a repro if the raw getter returns a string but the error persists.
- 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
- Use evaluate for text reads on sites with patched DOM getters.
- Keep browser/k6 versions consistent.
- Report stable repros upstream.
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
- Error while parsing selector `${selector}` - selector cannot
- "level" attribute must be compared to a number
- Role must not be empty
- Unexpected end of selector while parsing selector `${selecto
- Error while parsing selector `${selector}` - cannot use ${op
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/f9e0a6de76e69394.
Report an issue: GitHub.