grafana/k6 · error
invalid url
Error message
invalid url %q
What it means
Intended to be returned when the url= value of K6_BROWSER_SCREENSHOTS_OUTPUT fails url.ParseRequestURI. The guard is 'err != nil && u.Scheme != "" && u.Host != ""', but Go's ParseRequestURI returns a nil *url.URL on failure, so in practice this branch almost never fires and malformed URLs are often accepted silently. When it does fire (or via the related nil hazard), the fix is the same: supply a valid absolute http/https URL.
Solutions
- Use a fully-qualified absolute URL: url=https://upload.example.com/
- Verify the URL independently (curl -I) before putting it in the env var, since the parser's validation is loose
- If you maintain this code, note the guard should be err != nil && (u == nil || ...) — as written the message is nearly unreachable
Example fix
# before export K6_BROWSER_SCREENSHOTS_OUTPUT='url=cdn.example.com/upload' # after export K6_BROWSER_SCREENSHOTS_OUTPUT='url=https://cdn.example.com/upload'
Defensive patterns
Strategy: validation
Validate before calling
const v = process.env.K6_BROWSER_SCREENSHOTS_OUTPUT ?? '';
const urlPart = v.split(',').find(p => p.startsWith('url='));
if (urlPart) {
let u;
try { u = new URL(urlPart.slice(4)); } catch { u = null; }
if (!u || (u.protocol !== 'http:' && u.protocol !== 'https:')) {
throw new Error('url= must be an absolute http(s) URL with scheme and host');
}
} Prevention
- Always include the scheme: https://… not bare hostnames
- Validate the URL with new URL() or curl before the run — the Go-side guard is loose and rarely fires
- Treat remote-upload failures as possible fallout from an unvalidated URL that slipped through
When it happens
Trigger: Setting url= to a non-URL like 'url=localhost:9200/upload' or 'url=/upload' — values that fail request-URI parsing. Most such inputs are silently stored rather than rejected, surfacing later as upload failures.
Common situations: Omitting the scheme (example.com instead of https://example.com) in CI env vars; using a host:port value without a scheme; the error usually appears only in edge cases due to the guard logic, so verify URLs manually.
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
- parsing
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/d3e99ccaf54fa074.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/file_persister.go:83
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)
}
}
if presignedURL.getterURL == "" {
return presignedURLConfig{}, errors.New("missing required url")
}
return presignedURL, nil
}
View on GitHub (pinned to 01ffac6f24)