grafana/k6 · error · errBrowserNotFoundInRegistry

browser not found in registry. make sure to set browser…

Error message

browser not found in registry. make sure to set browser type option in scenario definition in order to use the browser module

What it means

k6 pre-launches one browser per VU iteration on the IterStart event and stores it in an internal registry keyed by iteration ID; the browser module fetches it lazily via getBrowser (internal/js/modules/k6/browser/browser/registry.go:396). If nothing was launched — almost always because no browser type option was configured for the scenario — the lookup returns errBrowserNotFoundInRegistry. It is k6's guard against using k6/browser without the required options.

Solutions

  1. Set the browser type option in the scenario: `export const options = { scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium' } } } } }`
  2. Or set it top-level so every scenario inherits it: `export const options = { browser: { type: 'chromium' } }`
  3. Import from 'k6/browser' (not 'k6/x/browser') and verify you run a modern k6 binary (browser module requires k6 >= 0.43; v1.x recommended)
  4. Check k6 output above this error — a failed browser launch for the iteration produces the same missing-registry lookup

Example fix

// before
import { browser } from 'k6/browser';
export default async function () {
  const page = await browser.newPage(); // no browser type configured
}

// after
import { browser } from 'k6/browser';
export const options = {
  scenarios: {
    ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium' } } },
  },
};
export default async function () {
  const page = await browser.newPage();
}
Defensive patterns

Strategy: validation

Validate before calling

// k6 options are static — declare them unconditionally next to the browser import
import { browser } from 'k6/browser';
export const options = {
  scenarios: {
    ui: { executor: 'shared-iterations', vus: 1, options: { browser: { type: 'chromium' } } },
  },
};

Prevention

When it happens

Trigger: Importing k6/browser and calling chromium/browser() (or any page API) in a script whose options block lacks `browser: { type: 'chromium' }` — at scenario level or top level; browser options defined in one scenario while the browser code runs in another; a failed per-iteration browser launch leaving the registry empty.

Common situations: Browser examples copied from docs with the options block dropped; migration from the old k6/x/browser extension where the option was not required; options refactor that moved browser config out of the scenario; running a very old k6 binary that does not pre-launch browsers.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/registry.go:33

	"go.opentelemetry.io/otel/attribute"
	oteltrace "go.opentelemetry.io/otel/trace"

	"go.k6.io/k6/v2/internal/js/modules/k6/browser/chromium"
	"go.k6.io/k6/v2/internal/js/modules/k6/browser/common"
	"go.k6.io/k6/v2/internal/js/modules/k6/browser/env"
	"go.k6.io/k6/v2/internal/js/modules/k6/browser/k6ext"
	browsertrace "go.k6.io/k6/v2/internal/js/modules/k6/browser/trace"
	"go.k6.io/k6/v2/internal/js/taskqueue"

	k6event "go.k6.io/k6/v2/internal/event"
	k6modules "go.k6.io/k6/v2/js/modules"
)

// errBrowserNotFoundInRegistry indicates that the browser instance
// for the iteration, which should have been initialized as a result
// of the IterStart event, has not been found in the registry. This
// might happen if browser type option is not set in scenario definition.
var errBrowserNotFoundInRegistry = errors.New("browser not found in registry. " +
	"make sure to set browser type option in scenario definition in order to use the browser module")

// pidRegistry keeps track of the launched browser process IDs.
type pidRegistry struct {
	mu  sync.RWMutex
	ids []int
}

// registerPid registers the launched browser process ID.
func (r *pidRegistry) registerPid(pid int) {
	r.mu.Lock()
	defer r.mu.Unlock()

	r.ids = append(r.ids, pid)
}

// Pids returns the launched browser process IDs.
func (r *pidRegistry) Pids() []int {

View on GitHub (pinned to 01ffac6f24)