{"record":{"id":"d3e99ccaf54fa074","repo":"grafana/k6","slug":"invalid-url-q","errorCode":null,"errorMessage":"invalid url %q","messagePattern":"invalid url %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/file_persister.go","lineNumber":83,"sourceCode":"\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}\n\n\tif presignedURL.getterURL == \"\" {\n\t\treturn presignedURLConfig{}, errors.New(\"missing required url\")\n\t}\n\n\treturn presignedURL, nil\n}\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/browser/file_persister.go#L65-L101","documentation":"Intended to reject an unparseable url= value in K6_BROWSER_SCREENSHOTS_OUTPUT (file_persister.go:83), but the guard is defective: url.ParseRequestURI returns a nil *url.URL on error, so the condition 'err != nil && u.Scheme != \"\" && u.Host != \"\"' never evaluates cleanly when parsing fails. In practice this exact error is nearly unreachable; bad URLs slip through unvalidated and fail later (or crash) at upload time.","triggerScenarios":"Setting url= to something that is not an absolute request URI, e.g. 'url=notaurl' or 'url=/relative/path'. Because of the broken condition the error usually does not fire; the failure surfaces later when the remote persister tries to PUT the screenshot to an unusable URL.","commonSituations":"Forgetting the scheme ('url=example.com/uploads'), using a relative path, or a typo'd hostname; the resulting symptom is a confusing downstream upload error instead of this clean message.","solutions":["Always set url= to a fully-qualified absolute URL with scheme and host: url=https://uploads.example.com/","Verify it parses and responds before the test: curl -fsSI \"$URL\" >/dev/null && echo ok","Add a pre-flight check in Go: if _, err := url.ParseRequestURI(v); err != nil { return err }","If you can reproduce this exact message or a nil-pointer panic near it, report the defect to k6 (the guard dereferences a nil URL)"],"exampleFix":"# before\nK6_BROWSER_SCREENSHOTS_OUTPUT=\"url=uploads.example.com/,basePath=/s\"\n# after\nK6_BROWSER_SCREENSHOTS_OUTPUT=\"url=https://uploads.example.com/,basePath=/s\"","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\nu=\"${K6_BROWSER_SCREENSHOTS_OUTPUT#url=}\"; u=\"${u%%,*}\"\ncase \"$u\" in\n  https://*/*|http://*/*) : ;;\n  *) echo \"url= must be an absolute http(s) URL ending with /, got: $u\" >&2; exit 1 ;;\nesac\ncurl -fsSI --max-time 5 \"$u\" >/dev/null || { echo \"upload URL not reachable: $u\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include scheme, host, and trailing slash in url=","Reachability-check the upload endpoint in CI before the load test","If a nil-pointer panic occurs near this code, report it upstream - the guard dereferences a nil URL"],"tags":["k6","browser","environment-variable","url-validation","screenshots"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}