grafana/k6 · error
%q is not a valid lifecycle
Error message
%q is not a valid lifecycle
What it means
PageGotoOptions.Parse validates the waitUntil option of page.goto() against the allowlist {'load', 'domcontentloaded', 'networkidle'} (map lifecycleEventToID). An exact, case-sensitive miss returns this error before any navigation starts; it is deterministic input validation.
Source
Thrown at internal/js/modules/k6/browser/common/page_options.go:81
Timeout: defaultTimeout,
}
}
// Parse parses the page go back/forward options.
func (o *PageGoBackForwardOptions) Parse(ctx context.Context, opts sobek.Value) error {
if common.IsNullish(opts) {
return nil
}
obj := opts.ToObject(k6ext.Runtime(ctx))
for _, k := range obj.Keys() {
switch k {
case "waitUntil":
lifeCycle := obj.Get(k).String()
if l, ok := lifecycleEventToID[lifeCycle]; ok {
o.WaitUntil = l
} else {
return fmt.Errorf("%q is not a valid lifecycle", lifeCycle)
}
case "timeout":
o.Timeout = time.Duration(obj.Get(k).ToInteger()) * time.Millisecond
}
}
return nil
}
// Parse parses the page reload options.
func (o *PageReloadOptions) Parse(ctx context.Context, opts sobek.Value) error {
rt := k6ext.Runtime(ctx)
if !common.IsNullish(opts) {
opts := opts.ToObject(rt)
for _, k := range opts.Keys() {
switch k {
case "waitUntil":
lifeCycle := opts.Get(k).String()View on GitHub (pinned to 93accf6570)
Solutions
- Use exactly 'load', 'domcontentloaded', or 'networkidle' (all lowercase)
- Prefer 'domcontentloaded' for faster, more stable waits; note networkidle is discouraged for loading pages
Example fix
// before
await page.goto('https://example.com/', { waitUntil: 'networkIdle' });
// after
await page.goto('https://example.com/', { waitUntil: 'networkidle' }); Defensive patterns
Strategy: validation
Validate before calling
const WAIT_UNTIL = ['load', 'domcontentloaded', 'networkidle'];
if (!WAIT_UNTIL.includes(waitUntil)) throw new Error(`invalid waitUntil: ${waitUntil}`); Type guard
const isValidWaitUntil = (v) => ['load','domcontentloaded','networkidle'].includes(v);
Prevention
- Define WAIT_UNTIL once per script and reuse it in every goto/reload
- Remember values are lowercase and case-sensitive
When it happens
Trigger: page.goto(url, { waitUntil: 'networkIdle' }) — casing error; 'domContentLoaded'; or Playwright-style 'commit'/'domcontentloaded ' with whitespace. Any value not exactly load/domcontentloaded/networkidle fails.
Common situations: Porting scripts from Playwright/Puppeteer that use different lifecycle names or casings; typos; trailing whitespace from templated config.
Related errors
- unmarshaling wait for load state %q: %w
- unsupported vision deficiency: %s
- exported 'setup' must be a function
- exported 'teardown' must be a function
- predicate function is not callable
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/04db8e3b6924e483.
Report an issue: GitHub.