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

  1. Prefix the registered name: `modules.Register("k6/x/myext", new(MyExt))`
  2. Update the script import to match exactly: `import myext from 'k6/x/myext';`
  3. Keep the name unique — ext.Register panics separately on duplicates
  4. 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

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


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/42e4abdc533305f8. Report an issue: GitHub.