grafana/k6 · error

executing page.on(' ') handler

Error message

executing page.on('%s') handler: %w

What it means

Produced inside the page.on(eventName, handler) callback wrapper when the user-supplied JavaScript handler throws. The handler is executed through the per-target task queue with the mapped event object; any exception it raises is wrapped with the event name and returned as the handler's error to the browser event dispatch layer.

Solutions

  1. Wrap the handler body in try/catch and swallow or log errors so one event cannot break the run.
  2. Guard optional accessors: if (!r.response()) return; before using response fields.
  3. Test the handler against the documented mapped objects (k6 Response/Request/ConsoleMessage) rather than Playwright's full API.
  4. Keep handlers cheap and synchronous; never await long operations inside page.on handlers.

Example fix

// before
page.on('response', r => console.log(r.status(), r.request().method()));

// after
page.on('response', r => {
  try { console.log(r.status(), r.request().method()); }
  catch (e) { console.log('handler error:', e.message); }
});
Defensive patterns

Strategy: try-catch

Try / catch

page.on('response', (r) => {
  try { console.log(r.status()); }
  catch (e) { console.log('page.on handler failed:', e.message); }
});

Prevention

When it happens

Trigger: A page.on('response', handler) body calling methods that do not exist on the mapped Response, dereferencing null (e.g. r.request() chain assumptions), or any JS exception (TypeError, ReferenceError) inside the handler when a matching event fires.

Common situations: Handlers written against the Playwright object model where k6's mapping differs; handlers that assume every response has a body or request available synchronously; forgetting that the handler runs for every matching event, including preflight OPTIONS and failed requests.

Related errors


AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18). Data as JSON: /api/errors/472e80e4c633dbe9. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/page_mapping.go:803

			common.PageEventMetric:          {mapp: mapMetricEvent, wait: true},
			common.PageEventRequest:         {mapp: mapRequestEvent},
			common.PageEventResponse:        {mapp: mapResponseEvent},
			common.PageEventRequestFinished: {mapp: mapRequestEvent},
			common.PageEventRequestFailed:   {mapp: mapRequestEvent},
		}
		pageEvent, ok := pageEvents[eventName]
		if !ok {
			return fmt.Errorf("unknown page on event: %q", eventName)
		}

		ctx := vu.Context()
		tq := vu.get(ctx, p.TargetID())

		return p.On(eventName, func(event common.PageEvent) error {
			wait := queueTask(ctx, tq, func() (sobek.Value, error) {
				_, err := handle(sobek.Undefined(), vu.Runtime().ToValue(pageEvent.mapp(vu, event)))
				if err != nil {
					return nil, fmt.Errorf("executing page.on('%s') handler: %w", eventName, err)
				}
				return nil, nil
			})
			if pageEvent.wait {
				if _, err := wait(); errors.Is(err, context.Canceled) {
					return errors.New("iteration ended before page.on handler completed executing")
				}
			}
			return nil
		})
	}
}

func parseWaitForFunctionArgs(
	rt *sobek.Runtime, timeout time.Duration, pageFunc, opts sobek.Value, gargs ...sobek.Value,
) (string, *common.FrameWaitForFunctionOptions, []any, error) {
	popts, err := parseFrameWaitForFunctionOptions(rt, opts, timeout)
	if err != nil {

View on GitHub (pinned to 8d06114777)