{"record":{"id":"1fbe7d1e250ade92","repo":"grafana/k6","slug":"attr-attribute-is-only-supported-for-roles","errorCode":null,"errorMessage":"\"${attr}\" attribute is only supported for roles: ${roles.slice().sort().map((role2) => `\"${role2}\"`).join(\", \")}","messagePattern":"\"(.+?)\" attribute is only supported for roles: (.+?)\"`\\)\\.join\\(\", \"\\)\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"internal/js/modules/k6/browser/common/js/injected_script.js","lineNumber":1150,"sourceCode":"  result.name = readIdentifier();\n  skipSpaces();\n  while (next() === \"[\") {\n    result.attributes.push(readAttribute());\n    skipSpaces();\n  }\n  if (!EOL)\n    syntaxError(void 0);\n  if (!result.name && !result.attributes.length)\n    throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - selector cannot be empty`);\n  return result;\n}\n\n// packages/injected/src/roleSelectorEngine.ts\nvar kSupportedAttributes = [\"selected\", \"checked\", \"pressed\", \"expanded\", \"level\", \"disabled\", \"name\", \"include-hidden\"];\nkSupportedAttributes.sort();\nfunction validateSupportedRole(attr, roles, role) {\n  if (!roles.includes(role))\n    throw new Error(`\"${attr}\" attribute is only supported for roles: ${roles.slice().sort().map((role2) => `\"${role2}\"`).join(\", \")}`);\n}\nfunction validateSupportedValues(attr, values) {\n  if (attr.op !== \"<truthy>\" && !values.includes(attr.value))\n    throw new Error(`\"${attr.name}\" must be one of ${values.map((v) => JSON.stringify(v)).join(\", \")}`);\n}\nfunction validateSupportedOp(attr, ops) {\n  if (!ops.includes(attr.op))\n    throw new Error(`\"${attr.name}\" does not support \"${attr.op}\" matcher`);\n}\nfunction validateAttributes(attrs, role) {\n  const options = { role };\n  for (const attr of attrs) {\n    switch (attr.name) {\n      case \"checked\": {\n        validateSupportedRole(attr.name, kAriaCheckedRoles, role);\n        validateSupportedValues(attr, [true, false, \"mixed\"]);\n        validateSupportedOp(attr, [\"<truthy>\", \"=\"]);\n        options.checked = attr.op === \"<truthy>\" ? true : attr.value;","sourceCodeStart":1132,"sourceCodeEnd":1168,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/js/injected_script.js#L1132-L1168","documentation":"An internal-invariant Go panic in ModuleSystem.getModuleInstanceFromGoModule (js/modules/require_impl.go:91-95). After linking and evaluating a goModule (a module implemented in Go, like k6/http), the code fetches the module instance the runtime associated with it and asserts it is a *goModuleInstance; any other concrete type means the runtime's module-instance bookkeeping disagrees with k6's wrapper. Like the message says, this is a k6 bug to report, not a script error, and as a raw panic it aborts the process rather than surfacing as a JS exception.","triggerScenarios":"Calling require() on a Go-implemented module, e.g. `const http = require('k6/http')` — Require (require_impl.go:35-37) routes goModules through getModuleInstanceFromGoModule. The panic fires when rt.GetModuleInstance(wm) returns a non-goModuleInstance value, typically after a sobek/k6 version change in how instances are cached or instantiated.","commonSituations":"Scripts written in CommonJS style that require() built-in k6 modules instead of importing them; upgrading k6 or its sobek dependency and hitting a module-instance regression; running a custom xk6 binary whose extensions interact with the module system in unsupported ways.","solutions":["Switch the affected module to a native ES import: `import http from 'k6/http';` — this uses the ESM evaluation path and avoids Require's go-module branch","Report the issue at https://github.com/grafana/k6/issues with the script and `k6 version` output","Reproduce with a minimal script (`const http = require('k6/http'); export default function(){}`) to attach to the report","Try another k6 release if you need to keep the require() style; check release notes for module-system fixes"],"exampleFix":"// before\nconst http = require('k6/http'); // panics in getModuleInstanceFromGoModule\n\n// after\nimport http from 'k6/http'; // ESM import path, no Require() go-module branch","handlingStrategy":"fallback","validationCode":"null","typeGuard":null,"tryCatchPattern":"// Raw Go panic from the module system — not catchable from JS.\n// Avoid the failing path entirely: use ESM imports instead of require() for Go-backed modules.\n// import http from 'k6/http';      // instead of: const http = require('k6/http');\n// import { check } from 'k6';      // instead of: const { check } = require('k6');","preventionTips":["Use `import x from 'k6/<module>'` for all built-in and Go-implemented modules; reserve require() for local file modules when possible","Smoke-test `const m = require('k6/http')` once per k6 upgrade; if it panics, switch that call site to import","Pin k6 in CI and review release notes for js/modules changes before upgrading","Report the panic (it is an acknowledged k6 bug) with script and version"],"tags":["commonjs","require","go-modules","internal-bug","panic","module-system"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}