grafana/k6 · error

%s

Error message

%s

What it means

When Frame.EvaluateGlobal()'s CDP call succeeds but returns exceptionDetails, k6 formats them via parseExceptionDetails and returns that text as the error. In other words: the transport worked, but the JS you passed threw an uncaught exception in the page's global context.

Source

Thrown at internal/js/modules/k6/browser/common/frame.go:895

func (f *Frame) Evaluate(pageFunc string, args ...any) (any, error) {
	f.log.Debugf("Frame:Evaluate", "fid:%s furl:%q", f.ID(), f.URL())

	return f.EvaluateWithContext(f.ctx, pageFunc, args...)
}

// EvaluateGlobal will evaluate the given JS code in the global object.
func (f *Frame) EvaluateGlobal(ctx context.Context, js string) error {
	action := runtime.Evaluate(js).WithAwaitPromise(true)

	var (
		exceptionDetails *runtime.ExceptionDetails
		err              error
	)
	if _, exceptionDetails, err = action.Do(cdp.WithExecutor(ctx, f.manager.session)); err != nil {
		return fmt.Errorf("evaluating JS in global context: %w", err)
	}
	if exceptionDetails != nil {
		return fmt.Errorf("%s", parseExceptionDetails(exceptionDetails))
	}

	return nil
}

// EvaluateHandle will evaluate provided page function within an execution context.
func (f *Frame) EvaluateHandle(pageFunc string, args ...any) (handle JSHandleAPI, _ error) {
	f.log.Debugf("Frame:EvaluateHandle", "fid:%s furl:%q", f.ID(), f.URL())

	evalHandle := func() (JSHandleAPI, error) {
		f.executionContextMu.RLock()
		defer f.executionContextMu.RUnlock()

		ec := f.executionContexts[mainWorld]
		if ec == nil {
			return nil, fmt.Errorf("evaluating handle for frame: execution context %q not found", mainWorld)
		}
		return ec.EvalHandle(f.ctx, pageFunc, args...) //nolint:wrapcheck

View on GitHub (pinned to 93accf6570)

Solutions

  1. Paste the exact JS string into DevTools console on the same page and fix the exception it reports.
  2. Guard inside the evaluated code: wrap in try/catch and return an error value instead of throwing.
  3. Ensure the code runs after the scripts/globals it depends on have loaded.

Example fix

// before
page.evaluateGlobal('JSON.parse(window.__cfg).urls[0]'); // throws if __cfg unset

// after
page.evaluateGlobal(`
  try {
    JSON.parse(window.__cfg || '{}').urls[0] || null;
  } catch (e) {
    null;
  }
`);
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the snippet runs cleanly in-page before using it:
await frame.evaluate(`(() => { try { ${js}; return 'ok'; } catch (e) { return 'err: ' + e.message; } })()`);

Try / catch

try {
  page.evaluateGlobal(js);
} catch (e) {
  console.warn('global JS threw in page:', e.message);
}

Prevention

When it happens

Trigger: The evaluated code references undefined globals, has a syntax error, or triggers a runtime error (null property access, JSON.parse of invalid data). With awaitPromise, a rejected promise also surfaces here.

Common situations: Stubbing window functions with a typo; evaluating code that assumes a library (jQuery) already loaded; awaiting a promise that rejects; version skew where a global API changed in the target page.

Related errors


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