{"record":{"id":"1d0e5b3f3fdc7a6c","repo":"grafana/k6","slug":"empty-header-key-received-q","errorCode":null,"errorMessage":"empty header key, received %q","messagePattern":"empty header key, received %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/file_persister.go","lineNumber":75,"sourceCode":"\n\t\t// A key with \"header.\" means that the header name is encoded in the\n\t\t// key, separated by a \".\". Split the header on \".\" to retrieve the\n\t\t// header name. The header value should be present in v from the previous\n\t\t// split.\n\t\tvar hv, hk string\n\t\tif strings.Contains(k, \"header.\") {\n\t\t\thv = v\n\n\t\t\thh := strings.Split(k, \".\")\n\t\t\tif len(hh) != 2 {\n\t\t\t\treturn presignedURLConfig{}, fmt.Errorf(\"format of header must be header.k=v, received %q\", s)\n\t\t\t}\n\n\t\t\tk = hh[0]\n\t\t\thk = hh[1]\n\n\t\t\tif hk == \"\" {\n\t\t\t\treturn presignedURLConfig{}, fmt.Errorf(\"empty header key, received %q\", s)\n\t\t\t}\n\t\t}\n\n\t\tswitch k {\n\t\tcase \"url\":\n\t\t\tu, err := url.ParseRequestURI(v)\n\t\t\tif err != nil && u.Scheme != \"\" && u.Host != \"\" {\n\t\t\t\treturn presignedURLConfig{}, fmt.Errorf(\"invalid url %q\", s)\n\t\t\t}\n\t\t\tpresignedURL.getterURL = v\n\t\tcase \"basePath\":\n\t\t\tpresignedURL.basePath = v\n\t\tcase \"header\":\n\t\t\tpresignedURL.headers[hk] = hv\n\t\tdefault:\n\t\t\treturn presignedURLConfig{}, fmt.Errorf(\"invalid option %q\", k)\n\t\t}\n\t}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/browser/file_persister.go#L57-L93","documentation":"A header entry in K6_BROWSER_SCREENSHOTS_OUTPUT has an empty header name: the key is 'header.' followed directly by '=' (file_persister.go:75). After splitting on '.', the name part is the empty string.","triggerScenarios":"K6_BROWSER_SCREENSHOTS_OUTPUT contains a segment like 'header.=value' - the key contains 'header.', splits into ['header',''], and the empty second part triggers this error. Often caused by a template variable that was meant to interpolate the header name but expanded to nothing.","commonSituations":"CI templates using 'header.${HEADER_NAME}=x' with an unset variable; hand-truncated values; refactoring that dropped the header name but left the prefix.","solutions":["Supply a real header name: header.Authorization=Bearer xyz","Check that any templated header-name variables are actually set in CI","Grep the env var for 'header.=' and fix or remove that segment"],"exampleFix":"# before\nK6_BROWSER_SCREENSHOTS_OUTPUT=\"url=https://h/,header.=secret\"\n# after\nK6_BROWSER_SCREENSHOTS_OUTPUT=\"url=https://h/,header.Authorization=secret\"","handlingStrategy":"validation","validationCode":"const empty = v.split(',').filter(s => s.startsWith('header.='));\nif (empty.length) throw new Error(`empty header name in: ${empty.join(', ')}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fail CI when templated header-name variables resolve to empty","Prefer a fixed, reviewed env value over templates for header names"],"tags":["k6","browser","environment-variable","parsing","http-headers"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}