grafana/k6 · critical · InvalidSelectorError
Error while parsing selector `${selector}` - cannot use ${op
Error message
Error while parsing selector `${selector}` - cannot use ${operator} in attribute with non-string matching value - ${value} What it means
A Go panic raised by modules.Register (js/modules/modules.go:17-24) when an extension registers itself under a name that does not start with the constant prefix 'k6/x/'. k6 reserves short internal names for built-in modules, so every externally registered JS module must live under the k6/x/ namespace; the check is a single strings.HasPrefix against extPrefix, and ext.Register then records the module. Because this is a plain panic, the binary (usually a custom xk6 build) aborts when registration runs at startup.
Source
Thrown at internal/js/modules/k6/browser/common/js/injected_script.js:1125
value += eat1();
if (value === "true") {
value = true;
} else if (value === "false") {
value = false;
} else {
if (!allowUnquotedStrings) {
value = +value;
if (Number.isNaN(value))
syntaxError("parsing attribute value");
}
}
}
skipSpaces();
if (next() !== "]")
syntaxError("parsing attribute value");
eat1();
if (operator !== "=" && typeof value !== "string")
throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with non-string matching value - ${value}`);
return { name: jsonPath.join("."), jsonPath, op: operator, value, caseSensitive };
}
const result = {
name: "",
attributes: []
};
result.name = readIdentifier();
skipSpaces();
while (next() === "[") {
result.attributes.push(readAttribute());
skipSpaces();
}
if (!EOL)
syntaxError(void 0);
if (!result.name && !result.attributes.length)
throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - selector cannot be empty`);
return result;
}View on GitHub (pinned to 93accf6570)
Solutions
- Prefix the registered name: `modules.Register("k6/x/myext", new(MyExt))`
- Update the script import to match exactly: `import myext from 'k6/x/myext';`
- Keep the name unique — ext.Register panics separately on duplicates
- If wrapping a third-party extension, register under your own k6/x/ name rather than the bare upstream path
Example fix
// before
modules.Register("mycompany/mq", new(MQ)) // panics: missing k6/x/ prefix
// after
modules.Register("k6/x/mycompany-mq", new(MQ))
// in the JS script:
// import mq from 'k6/x/mycompany-mq'; Defensive patterns
Strategy: validation
Validate before calling
package main
import (
"log"
"strings"
"go.k6.io/k6/v2/js/modules"
)
func registerExt(name string, mod any) {
const prefix = "k6/x/"
if !strings.HasPrefix(name, prefix) {
log.Fatalf("module name %q must be prefixed with %q", name, prefix)
}
modules.Register(name, mod)
} Try / catch
// A panic at registration time aborts the custom binary before any test runs;
// there is no runtime catch — validate names at build/startup instead.
defer func() {
if r := recover(); r != nil {
log.Fatalf("extension registration failed: %v", r)
}
}()
modules.Register(name, mod) Prevention
- Always register extensions as `k6/x/<name>`; keep the same string in the JS import specifier
- Centralize registration in one place instead of scattering Register calls
- Add a unit test or startup assert that every registered name has the k6/x/ prefix
- Keep names unique across extensions — ext.Register panics on duplicates
When it happens
Trigger: Building a custom k6 binary with xk6 (or a fork) whose extension calls `modules.Register(name, mod)` with a name like 'mycompany/mq', 'k6-mq' or 'mq' — anything missing the leading 'k6/x/'. Happens the moment the generated main initializes the module registry, before any test runs.
Common situations: Writing a first xk6 extension and copying a module path convention from npm or Go instead of k6's; renaming an extension without updating the Register call (which also breaks `import 'k6/x/...'` specifiers in scripts); upgrading k6 versions where registration moved to the js/modules API and old boilerplate no longer matches.
Related errors
- unsupported extension type: %T
- Error while parsing selector `${selector}` - selector cannot
- extension already registered: %s
- couldn't load module instance while resolving identifier %q
- "${attr}" attribute is only supported for roles: ${roles.sli
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/42e4abdc533305f8.
Report an issue: GitHub.