grafana/k6 · error
Malformed attribute selector: ${selector}
Error message
Malformed attribute selector: ${selector} What it means
Frame.IsEditable() (frame.go:1414) wraps the isEditable action failure as 'checking is %q editable'. The action resolves the selector to an attached element within Timeout and asks the page (via the injected utility) for the element's 'editable' state using a zero timeout, so the state check itself does not wait. Errors wrapped here are selector timeouts, strict-mode violations, frame/context destruction, or injected-script failures.
Source
Thrown at internal/js/modules/k6/browser/common/js/injected_script.js:1614
if (node.nodeType === 1 /*Node.ELEMENT_NODE*/) {
result.push(node);
}
}
return result;
}
}
class AttributeEngine {
constructor() {
this._evaluator = new SelectorEvaluatorImpl();
}
queryAll(root, selector) {
try {
this._evaluator.begin();
const parsed = parseAttributeSelector(selector, true);
if (parsed.name || parsed.attributes.length !== 1)
throw new Error("Malformed attribute selector: " + selector);
const { name, value, caseSensitive } = parsed.attributes[0];
const lowerCaseValue = caseSensitive ? null : value.toLowerCase();
let matcher;
if (value instanceof RegExp)
matcher = (s) => !!s.match(value);
else if (caseSensitive)
matcher = (s) => s === value;
else
matcher = (s) => s.toLowerCase().includes(lowerCaseValue);
const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, `[${name}]`);
return elements.filter((e) => matcher(e.getAttribute(name)));
} finally {
this._evaluator.end();
}
};
}
class LabelEngine {View on GitHub (pinned to 01ffac6f24)
Solutions
- Wait for the element first: await page.waitForSelector(sel, { state: 'attached', timeout: 10000 }).
- Use unique selectors (data-testid) to avoid strict-mode violations.
- Run the check on the frame that contains the element.
- Increase the per-call timeout on slow pages: page.isEditable(sel, { timeout: 60000 }).
Example fix
// before
const ok = await page.isEditable('#comment');
// after
await page.waitForSelector('#comment', { state: 'attached', timeout: 10000 });
const ok = await page.isEditable('#comment'); Defensive patterns
Strategy: try-catch
Validate before calling
await page.waitForSelector('#comment', { state: 'attached', timeout: 5000 }); Try / catch
try {
return await page.isEditable(sel, { timeout: 10000 });
} catch (e) {
if (String(e).includes('timed out')) throw new Error(`field never appeared: ${sel}`);
throw e;
} Prevention
- Wait for the field to attach before state checks.
- Use unique selectors under strict mode.
- Check state on the owning frame.
When it happens
Trigger: No element matches before opts.Timeout; multiple matches with Strict:true; frame navigates or detaches during the check; the injected isEditable evaluation errors on exotic shadow-DOM/custom elements.
Common situations: Asserting form fields are editable before typing in e2e smoke checks; checking fields that render after async hydration; iframes re-rendering mid-check; strict mode newly enabled after a k6 upgrade.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Error while parsing selector `${selector}` - unexpected symb
- Error while parsing selector `${selector}`: ${e.message}
- Error while parsing selector `${selector}` - cannot use ${op
- "${attr.name}" does not support "${attr.op}" matcher
- "name" attribute must have a value
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/11de44467d4227f9.
Report an issue: GitHub.