grafana/k6 · error

evaluating handle for frame: %w

Error message

evaluating handle for frame: %w

What it means

Frame.EvaluateHandle() resolves the main-world execution context and calls ec.EvalHandle. This error wraps that call's failure: the page function threw a JS exception, an argument failed to serialize into the context, or the context was destroyed during evaluation.

Source

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

// 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
	}

	f.waitForExecutionContext(mainWorld)
	handle, err := evalHandle()
	if err != nil {
		return nil, fmt.Errorf("evaluating handle for frame: %w", err)
	}

	applySlowMo(f.ctx)

	return handle, nil
}

// Fill fills out the first element found that matches the selector.
func (f *Frame) Fill(selector, value string, popts *FrameFillOptions) error {
	f.log.Debugf("Frame:Fill", "fid:%s furl:%q sel:%q val:%q", f.ID(), f.URL(), selector, value)

	if err := f.fill(selector, value, popts); err != nil {
		return fmt.Errorf("filling %q with %q: %w", selector, value, err)
	}

	applySlowMo(f.ctx)

	return nil

View on GitHub (pinned to 93accf6570)

Solutions

  1. Make the function defensive: null-check before use and run it in DevTools first.
  2. Wait for the elements/state the function depends on (waitForSelector).
  3. Pass only serializable args and use a proper function expression ('() => ...').

Example fix

// before
const h = page.evaluateHandle('() => document.querySelector("#x").dataset'); // #x may be null

// after
await page.waitForSelector('#x', { state: 'attached' });
const h = page.evaluateHandle('() => document.querySelector("#x").dataset');
Defensive patterns

Strategy: try-catch

Validate before calling

await frame.waitForSelector(sel, { state: 'attached', timeout: 30000 }); // if pageFunc touches an element

Try / catch

let h;
try {
  h = frame.evaluateHandle(pageFunc, ...args);
} catch (e) {
  console.warn('evaluateHandle failed:', e.message);
}

Prevention

When it happens

Trigger: pageFunc throws at runtime (bad selector inside evaluate, undefined reference); args contain non-serializable values; navigation destroys the context mid-call; invalid function expression syntax.

Common situations: Grabbing handles to elements that may not exist yet (querySelector returns null then code dereferences it); passing complex args; evaluating during form-submit navigations.

Related errors


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