grafana/k6 · error

width must be a number, got

Error message

width must be a number, got %s

What it means

Thrown by parseSize when the 'width' key of page.setViewportSize(size) is present but its value's runtime kind is neither Int64 nor Float64. Numeric strings, booleans, objects and arrays are rejected — only plain JavaScript numbers are accepted (nullish values are skipped).

Solutions

  1. Convert to numbers before the call: { width: Number(__ENV.VIEWPORT_W), height: Number(__ENV.VIEWPORT_H) }.
  2. Prefer browser.newContext({ viewport: { width: 1280, height: 720 } }) with literal numbers when the size is static.
  3. Validate with Number.isFinite before calling and fall back to a sane default.
  4. Never pass CSS-style strings like '1280px'.

Example fix

// before
await page.setViewportSize({ width: __ENV.W, height: __ENV.H });

// after
await page.setViewportSize({ width: Number(__ENV.W), height: Number(__ENV.H) });
Defensive patterns

Strategy: type-guard

Validate before calling

const w = Number(size.width);
if (!Number.isFinite(w)) throw new TypeError(`width must be a number, got ${typeof size.width}`);
await page.setViewportSize({ width: w, height: Number(size.height) });

Type guard

const isNumericSize = (s) => s == null || ((s.width === undefined || Number.isFinite(Number(s.width))) && (s.height === undefined || Number.isFinite(Number(s.height))));

Prevention

When it happens

Trigger: page.setViewportSize({ width: '1280', height: 720 }) (width as string); width from an environment variable or CSV without Number() conversion; { width: null } handled, but { width: 'auto' } or boolean values fail.

Common situations: Reading viewport dimensions from k6 options/env (__ENV.VIEWPORT_W) which always yields strings; sharing a config with a UI framework that serializes numbers to strings; partial objects copied from Playwright where width was allowed to be null.

Related errors


AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18). Data as JSON: /api/errors/729e87f52aaac85a. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/page_mapping.go:1206

func parseSize(rt *sobek.Runtime, opts sobek.Value) (*common.Size, error) {
	size := &common.Size{}
	if k6common.IsNullish(opts) {
		return size, nil
	}

	obj := opts.ToObject(rt)
	for _, k := range obj.Keys() {
		v := obj.Get(k)
		if k6common.IsNullish(v) {
			continue
		}
		switch k {
		case "width":
			switch v.ExportType().Kind() {
			case reflect.Int64, reflect.Float64:
				size.Width = v.ToFloat()
			default:
				return nil, fmt.Errorf("width must be a number, got %s", v.ExportType().Kind())
			}
		case "height":
			switch v.ExportType().Kind() {
			case reflect.Int64, reflect.Float64:
				size.Height = v.ToFloat()
			default:
				return nil, fmt.Errorf("height must be a number, got %s", v.ExportType().Kind())
			}
		}
	}

	return size, nil
}

// parsePageEmulateMediaOptions parses the page emulate media options from a Sobek value.
//
//nolint:unparam
func parsePageEmulateMediaOptions(

View on GitHub (pinned to 8d06114777)