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

  1. Encode polling as one of the quoted strings "raf", "mutation" or "interval" when producing JSON for this struct
  2. If you need a custom polling interval, pass it as a JS number through the scripting API (waitForFunction options) rather than through JSON
  3. 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

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


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/05fe180de489d54b. Report an issue: GitHub.