benbjohnson/litestream · critical
create per-connection replica client: %w
Error message
create per-connection replica client: %w
What it means
In openMainDB, when a VFS connection specifies cfg.ReplicaURL (via URI parameter 'replica_url' or per-connection config), a dedicated replica client is created from that URL with NewReplicaClientFromURL. This error wraps the failure of that URL-to-client construction. Litestream throws it because the read-only VFS cannot open the database without a working replica client backend.
Source
Thrown at vfs.go:160
case vfs.requiresTempFile(flags):
return vfs.openTempFile(name, flags)
default:
return nil, flags, sqlite3vfs.CantOpenError
}
}
func (vfs *VFS) openMainDB(name string, uriParameters map[string]string, flags sqlite3vfs.OpenFlag) (sqlite3vfs.File, sqlite3vfs.OpenFlag, error) {
cfg, err := vfs.configForOpen(name, uriParameters)
if err != nil {
return nil, 0, err
}
client := vfs.client
var perConnClient bool
if cfg != nil && cfg.ReplicaURL != "" {
client, err = NewReplicaClientFromURL(cfg.ReplicaURL)
if err != nil {
return nil, 0, fmt.Errorf("create per-connection replica client: %w", err)
}
if err := client.Init(context.Background()); err != nil {
if closer, ok := client.(io.Closer); ok {
if closeErr := closer.Close(); closeErr != nil {
return nil, 0, fmt.Errorf("init per-connection replica client: %w", errors.Join(err, closeErr))
}
}
return nil, 0, fmt.Errorf("init per-connection replica client: %w", err)
}
perConnClient = true
}
if client == nil {
return nil, 0, fmt.Errorf("no replica client configured: set LITESTREAM_REPLICA_URL, use SetVFSConfig, or pass replica_url in the database URI")
}
f := NewVFSFile(client, name, vfs.logger.With("name", name))
f.PollInterval = vfs.PollIntervalView on GitHub (pinned to 4ed7a308f6)
Solutions
- Check the replica_url scheme is one of the registered backends (s3, gs, azure, file, sftp) and spelled correctly.
- Ensure the storage backend package is imported (directly or via the litestream all-packages import) so its replica client is registered.
- URL-encode the replica_url properly inside the database URI; test the same URL with 'litestream replicate' to validate it.
- Fall back to the global configuration: set LITESTREAM_REPLICA_URL or call SetVFSConfig instead of the per-connection URL.
Example fix
// before
sql.Open("sqlite", "file:app.db?vfs=litestream&replica_url=s33://bucket/db")
// after
sql.Open("sqlite", "file:app.db?vfs=litestream&replica_url=s3://my-bucket/app.db") Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(replicaURL)
if err != nil || u.Scheme == "" {
return fmt.Errorf("invalid replica_url %q", replicaURL)
}
switch u.Scheme {
case "s3", "gs", "azure", "file", "sftp":
// ok
default:
return fmt.Errorf("unregistered replica scheme %q", u.Scheme)
} Try / catch
db, err := sql.Open("sqlite", dsn)
if err != nil {
var probeErr error
_, probeErr = litestream.NewReplicaClientFromURL(replicaURL)
return fmt.Errorf("open failed; replica client error: %w", errors.Join(err, probeErr))
} Prevention
- Test the replica URL with the litestream CLI before wiring it into connection strings
- Import the storage backend packages so schemes are registered at init
- URL-encode replica_url when embedding it in a SQLite URI
- Keep a config-level allowlist of supported schemes and validate at startup
When it happens
Trigger: Opening a database with a URI like 'file:/path/db?vfs=litestream&replica_url=s3://bucket/db' where the replica_url scheme is unregistered/unknown (e.g. typo 's33://'), or the URL is malformed so the scheme/endpoint cannot be extracted.
Common situations: Typos in the replica URL scheme; using a backend whose driver package was not imported/registered (e.g. missing Azure/GCS client registration); copy-pasting URLs with extra characters or wrong quoting in connection strings.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- no replica client configured: set LITESTREAM_REPLICA_URL, us
- database config required
- store required
- snapshot interval must be greater than 0
- snapshot retention must be greater than 0
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/208618bf77253d0a.
Report an issue: GitHub.