grafana/k6 · error
parsing page navigation options to
Error message
parsing page navigation options to %q: %w
What it means
Thrown synchronously by page.goto(url, opts) when FrameGotoOptions.Parse rejects an option. The failing branch is 'waitUntil': the string must unmarshal to a LifecycleEvent, and anything outside load, domcontentloaded, networkidle yields 'invalid lifecycle event: %q; must be one of: ...' (internal/js/modules/k6/browser/common/lifecycle.go:89-109), wrapped as 'parsing page navigation options to "<url>"'. referer and timeout are coerced and never fail. The URL is included in the message, which helps when navigating in a loop.
Solutions
- Use one of the three exact lowercase strings: 'load', 'domcontentloaded', 'networkidle'
- If waitUntil comes from the environment, default it: const waitUntil = ['load','domcontentloaded','networkidle'].includes(__ENV.WAIT) ? __ENV.WAIT : 'load'
- Check the URL in the message to find which navigation in a data-driven loop passed the bad option
Example fix
// before
await page.goto('https://k6.io', { waitUntil: 'networkIdle' });
// parsing page navigation options to "https://k6.io": parsing goto options:
// invalid lifecycle event: "networkIdle"; must be one of: load, domcontentloaded, networkidle
// after
await page.goto('https://k6.io', { waitUntil: 'networkidle' }); Defensive patterns
Strategy: validation
Validate before calling
const WAIT_UNTIL = new Set(['load', 'domcontentloaded', 'networkidle']);
function normalizeWaitUntil(v) {
return WAIT_UNTIL.has(v) ? v : 'load';
}
await page.goto(url, {
waitUntil: normalizeWaitUntil(__ENV.WAIT_UNTIL),
timeout: 30000,
}); Type guard
/** @param {unknown} v */
function isWaitUntil(v) {
return v === 'load' || v === 'domcontentloaded' || v === 'networkidle';
} Try / catch
try {
await page.goto(url, opts);
} catch (e) {
if (String(e).includes('invalid lifecycle event')) {
console.warn(`bad waitUntil for ${url}; falling back to 'load'`);
await page.goto(url, { ...opts, waitUntil: 'load' });
} else throw e;
} Prevention
- Only three exact lowercase values: load, domcontentloaded, networkidle
- Puppeteer's networkidle2 and Playwright's commit are not supported
- Default env-sourced waitUntil to 'load' instead of passing raw strings
- Use the URL echoed in the message to find the failing navigation in loops
When it happens
Trigger: page.goto(url, { waitUntil: 'networkIdle' }) — wrong casing, must be lowercase 'networkidle'; waitUntil: 'commit' or 'load' variants not in the enum such as 'interactive'; waitUntil: '' (empty string, e.g. from unset env var); waitUntil spelled 'domContentLoaded' instead of 'domcontentloaded'.
Common situations: Porting Puppeteer scripts ('networkidle2' is not accepted) or Playwright scripts ('commit' is not supported); waitUntil sourced from __ENV that is undefined; casing mistakes because the browser-module value differs from Playwright's camelCase constants.
Related errors
- parsing frame navigation options to
- " " attribute is only supported for roles: "`).join(", ")}
- evaluate requires a page function
- evaluateHandle requires a page function
- executing page.on(' ') handler
AI-assisted analysis of grafana/k6@8d06114777 (2026-09-14).
Data as JSON: /api/errors/aba263d512840826.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/page_mapping.go:241
return rt.ToValue(ml).ToObject(rt), nil
},
"getByText": func(text sobek.Value, opts sobek.Value) (*sobek.Object, error) {
if k6common.IsNullish(text) {
return nil, errors.New("missing required argument 'text'")
}
ptext, popts := parseGetByBaseOptions(vu.Context(), text, true, opts)
ml := mapLocator(vu, p.GetByText(ptext, popts))
return rt.ToValue(ml).ToObject(rt), nil
},
"goto": func(url string, opts sobek.Value) (*sobek.Promise, error) {
gopts, err := parseFrameGotoOptions(
rt, opts,
p.Referrer(),
p.NavigationTimeout(),
)
if err != nil {
return nil, fmt.Errorf("parsing page navigation options to %q: %w", url, err)
}
return promise(vu, func() (any, error) {
resp, err := p.Goto(url, gopts)
if err != nil {
return nil, err //nolint:wrapcheck
}
return mapResponse(vu, resp), nil
}), nil
},
"hover": func(selector string, opts sobek.Value) (*sobek.Promise, error) {
popts, err := parseFrameHoverOptions(rt, opts, p.MainFrame().Timeout())
if err != nil {
return nil, fmt.Errorf("parsing hover options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, p.Hover(selector, popts) //nolint:wrapcheck
}), nilView on GitHub (pinned to 8d06114777)