grafana/k6 · error
%q is not a valid DOM state
Error message
%q is not a valid DOM state
What it means
FrameWaitForSelectorOptions.Parse (frame_options.go:759) looks up the `state` option in domElementStateToID (frame.go:52-57), which defines exactly four valid states: "attached", "detached", "visible", "hidden". An unknown string aborts waitForSelector with this error before any waiting happens. The check is case-sensitive local validation, not a DOM query result.
Source
Thrown at internal/js/modules/k6/browser/common/frame_options.go:759
Strict: false,
Timeout: defaultTimeout,
}
}
// Parse parses the frame waitForSelector options.
func (o *FrameWaitForSelectorOptions) 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 "state":
state := opts.Get(k).String()
if s, ok := domElementStateToID[state]; ok {
o.State = s
} else {
return fmt.Errorf("%q is not a valid DOM state", state)
}
case "strict":
o.Strict = opts.Get(k).ToBoolean()
case "timeout":
o.Timeout = time.Duration(opts.Get(k).ToInteger()) * time.Millisecond
}
}
}
return nil
}
// FrameDispatchEventOptions are options for Frame.dispatchEvent.
type FrameDispatchEventOptions struct {
*FrameBaseOptions
}
// NewFrameDispatchEventOptions returns a new FrameDispatchEventOptions.View on GitHub (pinned to 93accf6570)
Solutions
- Use one of: "attached", "detached", "visible", "hidden" (lowercase)
- Remember the default is "visible"; if you got the error you likely set an explicit invalid value
- Constrain state in shared constants/TS types so only the four values can be passed
Example fix
// before
frame.waitForSelector('.status', { state: 'shown' });
// after
frame.waitForSelector('.status', { state: 'visible' });
// or wait for removal from DOM:
frame.waitForSelector('.loading', { state: 'detached' }); Defensive patterns
Strategy: validation
Validate before calling
const STATES = ['attached', 'detached', 'visible', 'hidden'];
if (opts && opts.state !== undefined && !STATES.includes(opts.state)) {
throw new Error(`state must be one of ${STATES.join(', ')} (got ${opts.state})`);
}
frame.waitForSelector(selector, opts); Type guard
function isDomState(v: unknown): v is 'attached' | 'detached' | 'visible' | 'hidden' {
return v === 'attached' || v === 'detached' || v === 'visible' || v === 'hidden';
} Prevention
- Default state is 'visible' — only pass state when you need a different condition
- Map vocabulary from other frameworks: displayed→visible, present→attached, gone→detached
When it happens
Trigger: frame.waitForSelector('#el', { state: 'shown' }), { state: 'Visible' }, { state: 'displayed' }, or values borrowed from other frameworks like 'attached-to-dom'. Default when omitted is "visible".
Common situations: Porting selectors logic from Selenium/Playwright vocabulary ('visible' vs 'displayed', 'attached' vs 'present'), or driving the state value from external test data that has not been constrained.
Related errors
- parsing goto options: %w
- parsing setContent options: %w
- wrong polling option value: %q; possible values: "raf", "mut
- parsing waitForNavigation options: %w
- parsing waitForURL options: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/001ea7903b9c1e32.
Report an issue: GitHub.