benbjohnson/litestream · error
replica client required before opening database
Error message
replica client required before opening database
What it means
DB.Open validates that db.Replica.Client is non-nil after checking the Replica itself. The Replica struct exists but carries no storage backend implementation, so Litestream cannot know where to replicate LTX files. Like the previous check, it is a fail-fast precondition enforced at open time.
Source
Thrown at db.go:785
}
// Open initializes the background monitoring goroutine.
func (db *DB) Open() (err error) {
db.mu.Lock()
if db.opened {
db.mu.Unlock()
return nil // already open
}
// Recreate context for fresh start (handles reopen after close)
db.ctx, db.cancel = context.WithCancel(context.Background())
db.mu.Unlock()
// Validate fields on database.
if db.Replica == nil {
return fmt.Errorf("replica required before opening database")
}
if db.Replica.Client == nil {
return fmt.Errorf("replica client required before opening database")
}
if db.MinCheckpointPageN <= 0 {
return fmt.Errorf("minimum checkpoint page count required")
}
// Clear old temporary files that my have been left from a crash.
if err := removeTmpFiles(db.metaPath); err != nil {
return fmt.Errorf("cannot remove tmp files: %w", err)
}
// Set the compactor client once before starting any goroutines.
db.compactor.VerifyCompaction = db.VerifyCompaction
db.compactor.RetentionEnabled = db.RetentionEnabled
db.compactor.client = db.Replica.Client
// Start monitoring SQLite database in a separate goroutine.
if db.MonitorInterval > 0 {
db.wg.Add(1)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Assign a concrete replica client, e.g. db.Replica.Client = s3.NewReplicaClient() with its fields set.
- For config-driven setups, verify the replica type in YAML maps to a registered backend and the client is built during config parsing.
- Log/inspect the Replica object right before Open() to confirm Client != nil.
Example fix
// before
db.Replica = litestream.NewReplica(db, "s3")
if err := db.Open(); err != nil { ... }
// after
db.Replica = litestream.NewReplica(db, "s3")
rc := s3.NewReplicaClient()
rc.Bucket, rc.Path, rc.Region = "my-bucket", "db", "us-east-1"
db.Replica.Client = rc
if err := db.Open(); err != nil { ... } Defensive patterns
Strategy: validation
Validate before calling
if db.Replica != nil && db.Replica.Client == nil {
return fmt.Errorf("replica %s: client backend not configured", db.Replica.Name())
} Prevention
- Construct replicas via factory functions (e.g. NewReplicaFromConfig) that always set Client.
- Unit-test DB construction paths to assert Replica.Client != nil.
When it happens
Trigger: Setting db.Replica = litestream.NewReplica(...) but never assigning db.Replica.Client; creating a Replica whose Client field was cleared or not deserialized from config.
Common situations: Library users wiring a replica manually and forgetting the backend client (S3, GCS, SFTP, file, etc.); custom ReplicaClient implementations assigned incorrectly; config parsing that created the replica but failed to instantiate the client silently.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- replica required before opening database
- sync interval must be greater than 0
- validation failed
- minimum checkpoint page count required
- cannot determine current position: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/64f249562151942e.
Report an issue: GitHub.