grafana/k6 · error
"level" attribute must be compared to a number
Error message
"level" attribute must be compared to a number
What it means
After evaluating element.innerHTML successfully (frame.go:1317), k6 asserts the CDP-returned value is a Go string; otherwise it returns 'unexpected type %T'. The DOM property is spec-defined as a string, so a non-string result means abnormal page behavior: JavaScript overriding the innerHTML getter on Element/HTMLElement prototypes, or a DevTools protocol value-conversion quirk. It is a defensive check and usually signals page tampering or a k6/browser-module bug rather than a script mistake.
Source
Thrown at internal/js/modules/k6/browser/common/js/injected_script.js:1197
validateSupportedRole(attr.name, kAriaSelectedRoles, role);
validateSupportedValues(attr, [true, false]);
validateSupportedOp(attr, ["<truthy>", "="]);
options.selected = attr.op === "<truthy>" ? true : attr.value;
break;
}
case "expanded": {
validateSupportedRole(attr.name, kAriaExpandedRoles, role);
validateSupportedValues(attr, [true, false]);
validateSupportedOp(attr, ["<truthy>", "="]);
options.expanded = attr.op === "<truthy>" ? true : attr.value;
break;
}
case "level": {
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;View on GitHub (pinned to 01ffac6f24)
Solutions
- Inspect what the page really returns: const v = await page.evaluate(`document.querySelector(sel).innerHTML`); console.log(typeof v).
- Read the markup via page.evaluate instead of the innerHTML API when prototypes are patched.
- Report to grafana/k6 with a minimal repro page if DevTools shows a string but the error persists.
- Launch a standard, pinned Chromium to rule out browser-specific behavior.
Example fix
// before
const html = await page.innerHTML('#app'); // unexpected type ...
// after
const html = await page.evaluate(`document.querySelector('#app').innerHTML`);
if (typeof html !== 'string') throw new Error('innerHTML getter is patched'); Defensive patterns
Strategy: fallback
Validate before calling
const t = await page.evaluate(`
(() => { const el = document.querySelector('#app'); return el ? typeof el.innerHTML : 'no-el'; })()
`);
if (t !== 'string') throw new Error('innerHTML getter patched'); Type guard
function isHtmlString(v) { return typeof v === 'string'; } Try / catch
try {
return await page.innerHTML(sel);
} catch (e) {
if (String(e).includes('unexpected type')) {
return await page.evaluate(`document.querySelector('${sel}').innerHTML`);
}
throw e;
} Prevention
- On tampering-prone sites, read markup via evaluate directly.
- Pin the Chromium version used by k6.
- Escalate persistent unexpected-type results to grafana/k6.
When it happens
Trigger: Page defines Object.defineProperty(HTMLElement.prototype, 'innerHTML', ...) returning non-strings; anti-bot or framework code patching DOM accessors; CDP returning an unserializable RemoteObject; Chromium version mismatch with the k6 browser module.
Common situations: Testing sites with bot-detection scripts that poison DOM getters; pages with aggressive custom-elements polyfills; unusual Chromium builds via executablePath.
Related errors
- Error while parsing selector `${selector}` - selector cannot
- "name" attribute must be a string or a regular expression
- 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/8fe3c3cd09afec7a.
Report an issue: GitHub.