grafana/k6 · error
unmarshaling polling type: %w
Error message
unmarshaling polling type: %w
What it means
PollingType.UnmarshalJSON (frame_options.go:181) decodes the `polling` field of FrameWaitForFunctionOptions from JSON and only accepts a quoted JSON string. If the payload contains a non-string (bare number, boolean, object), json.Unmarshal fails and the error is wrapped with this message. The accepted strings map through pollingTypeToID: "raf", "mutation", "interval"; unknown strings silently become the zero value instead of erroring.
Source
Thrown at internal/js/modules/k6/browser/common/frame_options.go:181
"raf": PollingRaf,
"mutation": PollingMutation,
"interval": PollingInterval,
}
// MarshalJSON marshals the enum as a quoted JSON string.
func (p PollingType) MarshalJSON() ([]byte, error) {
buffer := bytes.NewBufferString(`"`)
buffer.WriteString(pollingTypeToString[p])
buffer.WriteString(`"`)
return buffer.Bytes(), nil
}
// UnmarshalJSON unmarshals a quoted JSON string to the enum value.
func (p *PollingType) UnmarshalJSON(b []byte) error {
var j string
err := json.Unmarshal(b, &j)
if err != nil {
return fmt.Errorf("unmarshaling polling type: %w", err)
}
// Note that if the string cannot be found then it will be set to the zero value.
*p = pollingTypeToID[j]
return nil
}
type FrameWaitForFunctionOptions struct {
Polling PollingType `json:"polling"`
Interval int64 `json:"interval"`
Timeout time.Duration `json:"timeout"`
}
type FrameWaitForLoadStateOptions struct {
Timeout time.Duration `json:"timeout"`
}
type FrameWaitForNavigationOptions struct {
URL string `json:"url"`View on GitHub (pinned to 93accf6570)
Solutions
- Encode polling as one of the quoted strings "raf", "mutation" or "interval" when producing JSON for this struct
- If you need a custom polling interval, pass it as a JS number through the scripting API (waitForFunction options) rather than through JSON
- If you produce the JSON from Go, marshal with PollingType.MarshalJSON so it stays a quoted string
Example fix
// before (invalid JSON for the enum)
"options": { "polling": 100, "timeout": 30000 }
// after
"options": { "polling": "raf", "timeout": 30000 }
// custom interval via JS API instead:
frame.waitForFunction(() => !!window.done, {}, { polling: 100 }) Defensive patterns
Strategy: type-guard
Type guard
function isPollingJson(v: unknown): v is string {
return typeof v === 'string' && ['raf', 'mutation', 'interval'].includes(v);
}
// before serializing: if (!isPollingJson(opts.polling) && typeof opts.polling !== 'number') throw new Error('invalid polling'); Prevention
- Keep numeric polling intervals in the JS API layer, not in serialized option JSON
- Round-trip test your option JSON through the same marshal/unmarshal code paths k6 uses
When it happens
Trigger: Decoding option JSON into FrameWaitForFunctionOptions where polling is serialized as {"polling": 100} or {"polling": {"interval": 100}} rather than {"polling": "raf"}. Note the JavaScript API path (FrameWaitForFunctionOptions.Parse) handles numeric polling separately; this error only fires on the JSON unmarshal path.
Common situations: Tooling or tests that serialize/deserialize k6 browser options, or Go code that feeds program-generated JSON into the browser module's option structs with a numeric polling value.
Related errors
- wrong polling option value: %q; possible values: "raf", "mut
- unmarshaling %q to ReducedMotion: %w
- unmarshaling %q to ColorScheme: %w
- waiting for function: execution context %q not found
- converting argument '%v': %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/05fe180de489d54b.
Report an issue: GitHub.