grafana/k6 · error

"name" attribute must have a value

Error message

"name" attribute must have a value

What it means

Frame.InnerText() (frame.go:1330) wraps the innerText action failure with 'getting inner text of %q'. The action waits for a selector match in the attached state within Timeout and then evaluates element.innerText. Failures wrapped here are element/selector timeouts, strict-mode violations, detached frames or destroyed execution contexts during evaluation, and page-side exceptions (e.g., overridden innerText getters throwing).

Source

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

      }
      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;
      }
      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(", ")}.`);
      }
    }
  }

View on GitHub (pinned to 01ffac6f24)

Solutions

  1. Wait for the element (and ideally its text) before reading: await page.waitForSelector(sel, { timeout: 10000 }) or use locator(sel).waitFor().
  2. Use resilient, unique selectors (data-testid) so rerenders don't invalidate them.
  3. Call InnerText on the frame that actually owns the element.
  4. Give slow apps more time: page.innerText(sel, { timeout: 60000 }).

Example fix

// before
const txt = await page.innerText('.alert');

// after
const alert = page.locator('.alert');
await alert.waitFor({ state: 'visible', timeout: 10000 });
const txt = await alert.innerText();
Defensive patterns

Strategy: try-catch

Validate before calling

const el = page.locator('.alert');
await el.waitFor({ state: 'visible', timeout: 5000 });

Try / catch

try {
  return await page.innerText(sel, { timeout: 10000 });
} catch (e) {
  if (String(e).startsWith('getting inner text')) return null; // not rendered yet
  throw e;
}

Prevention

When it happens

Trigger: No element matches before opts.Timeout; multiple matches with Strict:true; navigation/detach between resolution and evaluation; page scripts throwing from a patched innerText getter.

Common situations: Reading text of elements populated after async fetches; asserting toast/confirmation text that disappears quickly; querying elements on the wrong frame; React re-renders swapping the node between resolution and read.

Related errors


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