grafana/k6 · error

empty header key, received

Error message

empty header key, received %q

What it means

Returned while parsing K6_BROWSER_SCREENSHOTS_OUTPUT when a header entry has an empty header name: the key splits as 'header.' + '' (i.e. the value looks like 'header.=value'). The parser explicitly rejects an empty name after the dot.

Solutions

  1. Provide a real header name: header.Authorization=xyz
  2. Remove the header entry entirely if not needed
  3. If the value is generated from a template, default the name to a placeholder like header.x=1 or drop the entry

Example fix

# before
export K6_BROWSER_SCREENSHOTS_OUTPUT='url=https://h/,header.=a'
# after
export K6_BROWSER_SCREENSHOTS_OUTPUT='url=https://h/,header.authorization=a'
Defensive patterns

Strategy: validation

Validate before calling

const v = process.env.K6_BROWSER_SCREENSHOTS_OUTPUT ?? '';
if (v) {
  const bad = v.split(',').filter(p => /^header\.=/.test(p));
  if (bad.length) throw new Error('header entries need a name: header.<name>=<value>');
}

Prevention

When it happens

Trigger: K6_BROWSER_SCREENSHOTS_OUTPUT containing 'header.=a' — a header key with nothing between 'header.' and the '='.

Common situations: Hand-building the variable with a placeholder header name that was never filled in; templating scripts (envsubst, Helm) that emit an empty variable into header.{{name}}.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/1d0e5b3f3fdc7a6c. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/file_persister.go:75

		// A key with "header." means that the header name is encoded in the
		// key, separated by a ".". Split the header on "." to retrieve the
		// header name. The header value should be present in v from the previous
		// split.
		var hv, hk string
		if strings.Contains(k, "header.") {
			hv = v

			hh := strings.Split(k, ".")
			if len(hh) != 2 {
				return presignedURLConfig{}, fmt.Errorf("format of header must be header.k=v, received %q", s)
			}

			k = hh[0]
			hk = hh[1]

			if hk == "" {
				return presignedURLConfig{}, fmt.Errorf("empty header key, received %q", s)
			}
		}

		switch k {
		case "url":
			u, err := url.ParseRequestURI(v)
			if err != nil && u.Scheme != "" && u.Host != "" {
				return presignedURLConfig{}, fmt.Errorf("invalid url %q", s)
			}
			presignedURL.getterURL = v
		case "basePath":
			presignedURL.basePath = v
		case "header":
			presignedURL.headers[hk] = hv
		default:
			return presignedURLConfig{}, fmt.Errorf("invalid option %q", k)
		}
	}

View on GitHub (pinned to 01ffac6f24)