grafana/k6 · error

unmarshaling %q to ReducedMotion: %w

Error message

unmarshaling %q to ReducedMotion: %w

What it means

ReducedMotion.UnmarshalJSON tried to json.Unmarshal the raw bytes into a Go string and that failed — the JSON value provided for the reducedMotion option is not a string (it is a number, boolean, object, array, or malformed JSON). Note the asymmetry: an unrecognized string silently maps to the zero value ('no-preference'); only non-string JSON produces this error.

Source

Thrown at internal/js/modules/k6/browser/common/page.go:117

var reducedMotionToID = map[string]ReducedMotion{ //nolint:gochecknoglobals
	"reduce":        ReducedMotionReduce,
	"no-preference": ReducedMotionNoPreference,
}

// MarshalJSON marshals the enum as a quoted JSON string.
func (r ReducedMotion) MarshalJSON() ([]byte, error) {
	buffer := bytes.NewBufferString(`"`)
	buffer.WriteString(reducedMotionToString[r])
	buffer.WriteString(`"`)
	return buffer.Bytes(), nil
}

// UnmarshalJSON unmarshals a quoted JSON string to the enum value.
func (r *ReducedMotion) UnmarshalJSON(b []byte) error {
	var j string
	err := json.Unmarshal(b, &j)
	if err != nil {
		return fmt.Errorf("unmarshaling %q to ReducedMotion: %w", b, err)
	}
	// Note that if the string cannot be found then it will be set to the zero value.
	*r = reducedMotionToID[j]
	return nil
}

// Screen represents a device screen.
type Screen struct {
	Width  int64 `js:"width"`
	Height int64 `js:"height"`
}

// ColorScheme represents a browser color scheme.
type ColorScheme string

// Valid color schemes.
const (
	ColorSchemeLight        ColorScheme = "light"

View on GitHub (pinned to 93accf6570)

Solutions

  1. Pass one of the string values 'reduce' or 'no-preference' for reducedMotion
  2. If options come from JSON config, ensure the value is a quoted JSON string
  3. Validate options shape before the run: k6 inspect script.js shows the parsed options

Example fix

// before
const ctx = browser.newContext({ reducedMotion: 1 }); // not a string

// after
const ctx = browser.newContext({ reducedMotion: 'reduce' });
Defensive patterns

Strategy: type-guard

Validate before calling

const rm = opts.reducedMotion;
if (rm !== undefined && typeof rm !== 'string') { throw new TypeError('reducedMotion must be a string: "reduce" | "no-preference"'); }

Type guard

function isValidReducedMotion(v) {
  return v === undefined || v === 'reduce' || v === 'no-preference';
}

Prevention

When it happens

Trigger: Passing reducedMotion as a non-string in browser.newContext/newPage options, e.g. reducedMotion: 1, reducedMotion: true, or reducedMotion: {name: 'reduce'}; also feeding malformed JSON when the option is supplied through JSON config (k6 cloud / --config JSON or environment-variable serialized options).

Common situations: Options templating that injects booleans/numbers; env-var config (K6_BROWSER... or --config file) where the value lost its quotes; scripts ported from Playwright that pass enum objects instead of strings.

Related errors


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