{"record":{"id":"1840f29d4fb8b381","repo":"grafana/k6","slug":"parsing-s-w","errorCode":null,"errorMessage":"parsing %s: %w","messagePattern":"parsing (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/file_persister.go","lineNumber":30,"sourceCode":"\ntype presignedURLConfig struct {\n\tgetterURL string\n\theaders   map[string]string\n\tbasePath  string\n}\n\n// newScreenshotPersister will return either a persister that persists file to the local\n// disk or uploads the files to a remote location. This decision depends on whether\n// the K6_BROWSER_SCREENSHOTS_OUTPUT env var is setup with the correct configs.\nfunc newScreenshotPersister(envLookup env.LookupFunc) (filePersister, error) {\n\tenvVar, ok := envLookup(env.ScreenshotsOutput)\n\tif !ok || envVar == \"\" {\n\t\treturn &storage.LocalFilePersister{}, nil\n\t}\n\n\tpopts, err := parsePresignedURLEnvVar(envVar)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing %s: %w\", env.ScreenshotsOutput, err)\n\t}\n\n\treturn storage.NewRemoteFilePersister(popts.getterURL, popts.headers, popts.basePath), nil\n}\n\n// parsePresignedURLEnvVar will parse a value such as:\n// url=https://127.0.0.1/,basePath=/screenshots,header.1=a,header.2=b\n// and return them.\n//\n\nfunc parsePresignedURLEnvVar(envVarValue string) (presignedURLConfig, error) {\n\tss := strings.Split(envVarValue, \",\")\n\n\tpresignedURL := presignedURLConfig{\n\t\theaders: make(map[string]string),\n\t}\n\tfor _, s := range ss {\n\t\t// The key value pair should be of the form key=value, so split","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/js/modules/k6/browser/browser/file_persister.go#L12-L48","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"# before\nexport K6_BROWSER_SCREENSHOTS_OUTPUT='https://cdn.example.com/upload,base=/shots'\n# after\nexport K6_BROWSER_SCREENSHOTS_OUTPUT='url=https://cdn.example.com/upload,basePath=/shots,header.1=auth-token'","handlingStrategy":"validation","validationCode":"#!/usr/bin/env node\nconst v = process.env.K6_BROWSER_SCREENSHOTS_OUTPUT;\nif (v !== undefined && v !== '') {\n  const parts = v.split(',');\n  const shapeOk = parts.every(p => p.split('=').length === 2);\n  const keysOk = parts.every(p => /^(url|basePath|header\\.[^,.]+)$/.test(p.split('=')[0]));\n  const hasUrl = parts.some(p => p.startsWith('url='));\n  if (!(shapeOk && keysOk && hasUrl)) {\n    console.error('K6_BROWSER_SCREENSHOTS_OUTPUT must be url=<abs-url>[,basePath=..][,header.k=v]');\n    process.exit(1);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["k6","browser","screenshots","environment-variable","configuration"],"backgroundTag":"invalid-env-var-format","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}