grafana/k6 · error
parsing
Error message
parsing %s: %w
What it means
Returned while the k6 browser module initializes (browser/module.go:127) when the K6_BROWSER_SCREENSHOTS_OUTPUT environment variable is set but its value cannot be parsed as a presigned-URL config. Any of the specific parse failures (bad k=v format, bad header, invalid option, invalid url, or 'missing required url') bubbles up wrapped as 'parsing K6_BROWSER_SCREENSHOTS_OUTPUT: ...'. Because it happens at module init, the whole test run aborts before any script executes.
Solutions
- Fix the value to the documented format: url=<absolute-url>,basePath=<dir>,header.<name>=<value> (url= is required; headers/basePath optional)
- Unset K6_BROWSER_SCREENSHOTS_OUTPUT to fall back to saving screenshots on local disk (LocalFilePersister)
- Echo the variable in your shell/CI before k6 run to catch paste errors
Example fix
# before export K6_BROWSER_SCREENSHOTS_OUTPUT='https://cdn.example.com/upload,base=/shots' # after export K6_BROWSER_SCREENSHOTS_OUTPUT='url=https://cdn.example.com/upload,basePath=/shots,header.1=auth-token'
Defensive patterns
Strategy: validation
Validate before calling
#!/usr/bin/env node
const v = process.env.K6_BROWSER_SCREENSHOTS_OUTPUT;
if (v !== undefined && v !== '') {
const parts = v.split(',');
const shapeOk = parts.every(p => p.split('=').length === 2);
const keysOk = parts.every(p => /^(url|basePath|header\.[^,.]+)$/.test(p.split('=')[0]));
const hasUrl = parts.some(p => p.startsWith('url='));
if (!(shapeOk && keysOk && hasUrl)) {
console.error('K6_BROWSER_SCREENSHOTS_OUTPUT must be url=<abs-url>[,basePath=..][,header.k=v]');
process.exit(1);
}
} Prevention
- Run a CI preflight check on K6_BROWSER_SCREENSHOTS_OUTPUT before k6 run
- Unset the variable in dev to fall back to local-disk screenshots
- Start from the canonical example 'url=https://host/,basePath=/dir,header.1=v' and edit incrementally
When it happens
Trigger: Exporting K6_BROWSER_SCREENSHOTS_OUTPUT with a malformed value: missing the required url= segment, a segment without '=', an unknown key like ulr=, or a bad header entry — e.g. K6_BROWSER_SCREENSHOTS_OUTPUT='basePath=/shots,header.1=a'.
Common situations: Configuring remote screenshot upload in CI (exporting the var in a pipeline) with a typo'd or partially-pasted value; setting the var to a bare URL without the url= prefix; leftover experimental values from another tool.
Related errors
- empty header key, received
- format of header must be header.k=v, received
- format of value must be k=v, received
- invalid option
- invalid url
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/1840f29d4fb8b381.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/file_persister.go:30
type presignedURLConfig struct {
getterURL string
headers map[string]string
basePath string
}
// newScreenshotPersister will return either a persister that persists file to the local
// disk or uploads the files to a remote location. This decision depends on whether
// the K6_BROWSER_SCREENSHOTS_OUTPUT env var is setup with the correct configs.
func newScreenshotPersister(envLookup env.LookupFunc) (filePersister, error) {
envVar, ok := envLookup(env.ScreenshotsOutput)
if !ok || envVar == "" {
return &storage.LocalFilePersister{}, nil
}
popts, err := parsePresignedURLEnvVar(envVar)
if err != nil {
return nil, fmt.Errorf("parsing %s: %w", env.ScreenshotsOutput, err)
}
return storage.NewRemoteFilePersister(popts.getterURL, popts.headers, popts.basePath), nil
}
// parsePresignedURLEnvVar will parse a value such as:
// url=https://127.0.0.1/,basePath=/screenshots,header.1=a,header.2=b
// and return them.
//
func parsePresignedURLEnvVar(envVarValue string) (presignedURLConfig, error) {
ss := strings.Split(envVarValue, ",")
presignedURL := presignedURLConfig{
headers: make(map[string]string),
}
for _, s := range ss {
// The key value pair should be of the form key=value, so splitView on GitHub (pinned to 01ffac6f24)