benbjohnson/litestream · error
replica url scheme required: %s
Error message
replica url scheme required: %s
What it means
ParseReplicaURLWithQuery requires every replica URL to carry a scheme; when url.Parse yields an empty scheme (bare path like "/path/to/replica" or "localhost:9000/bucket"), this error is returned. The library cannot pick a storage backend without a scheme.
Source
Thrown at replica_url.go:103
if strings.HasPrefix(strings.ToLower(s), "s3://arn:") {
scheme, host, urlPath, query, err := parseS3AccessPointURL(s)
return scheme, host, urlPath, query, nil, err
}
u, err := url.Parse(s)
if err != nil {
return "", "", "", nil, nil, err
}
switch u.Scheme {
case "file":
scheme, u.Scheme = u.Scheme, ""
// Remove query params from path for file URLs
u.RawQuery = ""
return scheme, "", path.Clean(u.String()), nil, nil, nil
case "":
return u.Scheme, u.Host, u.Path, nil, nil, fmt.Errorf("replica url scheme required: %s", s)
default:
return u.Scheme, u.Host, strings.TrimPrefix(path.Clean(u.Path), "/"), u.Query(), u.User, nil
}
}
// parseS3AccessPointURL parses an S3 Access Point URL (s3://arn:...).
func parseS3AccessPointURL(s string) (scheme, host, urlPath string, query url.Values, err error) {
const prefix = "s3://"
if !strings.HasPrefix(strings.ToLower(s), prefix) {
return "", "", "", nil, fmt.Errorf("invalid s3 access point url: %s", s)
}
arnWithPath := s[len(prefix):]
// Split off query string if present
var queryStr string
if idx := strings.IndexByte(arnWithPath, '?'); idx != -1 {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Prefix the path with file:// for local replicas (file:///mnt/backup/db).
- Add the correct storage scheme to the URL (s3://, gs://, abs://, sftp://, webdav://).
- Validate the replica URL in config before starting litestream (scheme non-empty).
- Check env-var expansion in the config file didn't drop the scheme prefix.
Example fix
// before: config with bare path
replica: { url: "/mnt/backup/db" } // replica url scheme required
// after
replica: { url: "file:///mnt/backup/db" } Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(replicaURL)
if err != nil { return err }
if u.Scheme == "" { return fmt.Errorf("replica URL %q needs a scheme (file://, s3://, gs://, ...)", replicaURL) } Type guard
func hasReplicaScheme(rawURL string) bool {
u, err := url.Parse(rawURL)
return err == nil && u.Scheme != ""
} Try / catch
if _, err := litestream.ParseReplicaURL(cfg.ReplicaURL); err != nil {
return fmt.Errorf("invalid replica URL in config: %w", err)
} Prevention
- Always use absolute replica URLs with explicit scheme in litestream.yml.
- Prefix local paths with file:// (file:///mnt/backup/db).
- Check env-var expansion in configs didn't swallow the scheme prefix.
- Fail fast on config validation before starting the Store.
When it happens
Trigger: Passing a replica URL string with no scheme to ParseReplicaURL/NewReplicaClientFromURL — e.g. a filesystem path without the file:// prefix, or a host/bucket string with no s3:// prefix.
Common situations: YAML config with `url: /mnt/backup/db` instead of `file:///mnt/backup/db`; passing `mybucket/db` instead of `s3://mybucket/db`; env-substitution producing an empty scheme (`$REPLICA_TYPE://...` with REPLICAS_TYPE unset is a different case, but a URL of only a path hits this).
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- heartbeat URL must be a valid HTTP or HTTPS URL
- file replica path required
- bucket required for gs replica URL
- oss: invalid url scheme
- host required for webdav replica URL
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/5e15e386dfe316af.
Report an issue: GitHub.