benbjohnson/litestream · error
parse query string: %w
Error message
parse query string: %w
What it means
After splitting the query string off an S3 Access Point URL, parseS3AccessPointURL parses it with url.ParseQuery; malformed query components are wrapped as "parse query string". This means the s3://arn:... URL's query portion is not valid URL-encoded key=value pairs.
Source
Thrown at replica_url.go:135
arnWithPath := s[len(prefix):]
// Split off query string if present
var queryStr string
if idx := strings.IndexByte(arnWithPath, '?'); idx != -1 {
queryStr = arnWithPath[idx+1:]
arnWithPath = arnWithPath[:idx]
}
bucket, key, err := splitS3AccessPointARN(arnWithPath)
if err != nil {
return "", "", "", nil, err
}
// Parse query string if present
if queryStr != "" {
query, err = url.ParseQuery(queryStr)
if err != nil {
return "", "", "", nil, fmt.Errorf("parse query string: %w", err)
}
}
return "s3", bucket, CleanReplicaURLPath(key), query, nil
}
// splitS3AccessPointARN splits an S3 Access Point ARN into bucket and key components.
func splitS3AccessPointARN(s string) (bucket, key string, err error) {
lower := strings.ToLower(s)
const marker = ":accesspoint/"
idx := strings.Index(lower, marker)
if idx == -1 {
return "", "", fmt.Errorf("invalid s3 access point arn: %s", s)
}
nameStart := idx + len(marker)
if nameStart >= len(s) {
return "", "", fmt.Errorf("invalid s3 access point arn: %s", s)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Fix or remove the malformed query string after '?' in the URL.
- Percent-encode special characters (use url.QueryEscape / QueryEscape for values).
- Drop the query entirely if no parameters are needed for the replica.
- Validate the URL with url.Parse/url.ParseQuery in config loading before starting replication.
Example fix
// before
u := "s3://arn:aws:s3:us-east-1:123:accesspoint/ap/db?path=100%" // parse query string error
// after
u := "s3://arn:aws:s3:us-east-1:123:accesspoint/ap/db?path=" + url.QueryEscape("100%") Defensive patterns
Strategy: validation
Validate before calling
if i := strings.Index(replicaURL, "?"); i >= 0 {
if _, err := url.ParseQuery(replicaURL[i+1:]); err != nil { return fmt.Errorf("bad query in replica URL: %w", err) }
} Type guard
func validQueryString(s string) bool { _, err := url.ParseQuery(s); return err == nil } Try / catch
if _, err := litestream.ParseReplicaURLWithQuery(rawURL); err != nil {
if strings.Contains(err.Error(), "parse query string") { return fmt.Errorf("URL-encode the query values in %q", rawURL) }
return err
} Prevention
- Always url.QueryEscape query values appended to replica URLs.
- Remove unneeded query strings from Access Point URLs.
- Run url.ParseQuery on config URLs before starting replication.
- Beware shell/templating corruption of '%' characters in query strings.
When it happens
Trigger: Passing an s3://arn:... URL whose query string fails url.ParseQuery — e.g. a bare '%' escape like ?path=100%, or invalid percent-encodings after '?' in the Access Point URL.
Common situations: Unescaped '%' in paths/keys appended to Access Point URLs; shell or templating corruption of query strings; hand-built URLs missing URL-encoding of special characters.
Understand the failure class
Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.
Related errors
- parse replica url: %w
- invalid s3 access point url: %s
- heartbeat URL must be a valid HTTP or HTTPS URL
- lease not held
- failed to delete files:
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/7409768816ce6a66.
Report an issue: GitHub.