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:wrapcheckView on GitHub (pinned to 93accf6570)
Solutions
- Paste the exact JS string into DevTools console on the same page and fix the exception it reports.
- Guard inside the evaluated code: wrap in try/catch and return an error value instead of throwing.
- 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
- Wrap global snippets in try/catch inside the page.
- Confirm referenced globals exist on the loaded page.
- Test snippets in DevTools on the exact page state.
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
- extracting value from remote object with ID %s: %w
- evaluating JS in global context: %w
- WebSocket endpoint cannot be empty
- can't fetch the page for unknown reason
- errorText
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/f7cace81caef40dc.
Report an issue: GitHub.