grafana/k6 · critical

ErrFatal

ErrFatal

Error message

fatal error

What it means

k6error.ErrFatal (k6error/internal.go:8-15) is a sentinel, not a standalone message: browser-module errors wrapped with it — e.g. 'on create page event failed to return a page' (browser_context.go:421) — tell the mapping layer, via panicIfFatalError (browser/helpers.go:20), to abort the whole test run instead of just the current iteration, because the error would recur with certainty on retry.

Source

Thrown at internal/js/modules/k6/browser/k6error/internal.go:15

// Package k6error contains ErrFatal.
package k6error

import (
	"errors"
)

// ErrFatal should be wrapped into an error
// to signal to the mapping layer that the error
// is a fatal error and we should abort the whole
// test run, not just the current iteration. It
// should be used in cases where if the iteration
// ran again then there's a 100% chance that it
// will end up running into the same error.
var ErrFatal = errors.New("fatal error")

View on GitHub (pinned to 93accf6570)

Solutions

  1. Read the wrapped cause printed alongside 'fatal error' — it names the real failure; fix that root cause
  2. Fix lifecycle handling: don't close the browser context while page creation or events are pending
  3. Create pages fresh per iteration from a long-lived context instead of reusing closed handles
  4. Upgrade k6 to the latest version if the wrapped cause points at an internal browser-module bug

Example fix

// before
const page = await context.newPage();
// ... later, in another iteration reusing a closed context:
const page2 = await context.newPage(); // fatal after close

// after
// keep the context open for the whole test; create pages per iteration
export default async function () {
  const page = await context.newPage();
  await page.goto('https://example.com/');
  await page.close();
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Structural preflight: keep the context alive for the whole test
if (!context || context.isClosed?.()) { context = await browser.newContext(); } // keep open across iterations
const page = await context.newPage();

Try / catch

try {
  const page = await context.newPage();
} catch (e) {
  if (String(e.message).includes('fatal error')) {
    // abort the run deliberately: report and exit non-zero, do not retry
    console.error('fatal browser error, aborting:', e.message);
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: Structural failures during browser lifecycle operations: page-creation events yielding a non-page object, pages/contexts used after close, or any internal state where re-running the iteration cannot succeed.

Common situations: Racing context.close() with pending page creation; reusing pages or contexts across iterations after they were closed; internal k6/browser bugs in specific versions where an event returns an unexpected object.

Related errors


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