benbjohnson/litestream · critical
init per-connection replica client: %w
Error message
init per-connection replica client: %w
What it means
In openMainDB, after creating a per-connection replica client from cfg.ReplicaURL, the client must be initialized with client.Init(context.Background()). This error is returned when Init fails AND the subsequent client.Close() also fails; both errors are joined with errors.Join. Litestream throws it because an uninitialized replica client cannot serve reads and the failed client also could not be cleaned up, signalling two simultaneous problems.
Source
Thrown at vfs.go:165
}
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.PollInterval
f.CacheSize = vfs.CacheSize
f.vfs = vfs
f.perConnClient = perConnClient
if cfg != nil {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Read the joined error: fix the underlying Init failure first (credentials, endpoint, bucket existence, network reachability).
- Validate the replica_url independently before opening (e.g. construct and Init the client in a probe, or run 'litestream ltx -replica <url>').
- Check environment variables/credentials for the backend (AWS_*, GOOGLE_APPLICATION_CREDENTIALS, AZURE_STORAGE_*) are present and valid.
- If Close errors persist, upgrade the storage backend package — a failing Close on an already-failed client usually indicates a driver bug.
Defensive patterns
Strategy: try-catch
Validate before calling
client, err := litestream.NewReplicaClientFromURL(replicaURL)
if err == nil {
if err := client.Init(ctx); err != nil { return fmt.Errorf("replica unreachable: %w", err) }
} Try / catch
db, err := sql.Open("sqlite", dsn)
if err != nil {
var joined interface{ Unwrap() []error }
if errors.As(err, &multiErr) { /* inspect each joined error */ }
return retryWithBackoff(func() error { return reopenDB(dsn) })
} Prevention
- Probe Init on the replica URL during application startup, before serving traffic
- Validate cloud credentials exist (AWS_*, GOOGLE_APPLICATION_CREDENTIALS, AZURE_STORAGE_*) at boot
- Use short health-check calls against the storage backend to catch auth/network issues early
- Keep backend driver packages updated so Close failure paths are fixed
When it happens
Trigger: Opening a VFS database whose per-connection replica_url points to a backend that fails Init (bad credentials, unreachable endpoint, missing bucket) and where the client implements io.Closer but Close() returns an error (e.g. session cleanup failure on sftp, HTTP client close error).
Common situations: Expired or wrong cloud credentials combined with flaky network; SFTP backend whose SSH session teardown fails; a custom ReplicaClient with buggy Close implementation.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- failed to create GCS client (bucket: %s): %w
- failed to list objects in GCS bucket %s (path: %s): %w
- gs: cannot delete object %q: %w
- gs: cannot delete ltx file %q: %w
- fetch ltx files: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/9ff1f255eea099b1.
Report an issue: GitHub.