benbjohnson/litestream · error
enable database: %w
Error message
enable database: %w
What it means
EnableDB checks the context for cancellation before performing the (uncancellable) db.Open(); if ctx is already done it returns 'enable database: <ctx err>'. This prevents starting a long, non-cancellable open for a caller that has already given up.
Source
Thrown at store.go:393
return nil
}
// EnableDB starts replication for a registered database.
// The context is checked for cancellation before opening.
// Note: db.Open() itself does not support cancellation.
func (s *Store) EnableDB(ctx context.Context, path string) error {
db := s.FindDB(path)
if db == nil {
return fmt.Errorf("database not found: %s", path)
}
if db.IsOpen() {
return fmt.Errorf("database already enabled: %s", path)
}
// Check for cancellation before starting open
if err := ctx.Err(); err != nil {
return fmt.Errorf("enable database: %w", err)
}
if err := db.Open(); err != nil {
return fmt.Errorf("open database: %w", err)
}
return nil
}
// DisableDB stops replication for a database.
func (s *Store) DisableDB(ctx context.Context, path string) error {
db := s.FindDB(path)
if db == nil {
return fmt.Errorf("database not found: %s", path)
}
if !db.IsOpen() {
return fmt.Errorf("database already disabled: %s", path)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Retry EnableDB with a fresh context (context.WithTimeout) if the enable is still wanted
- Check ctx.Err() at the call site before invoking EnableDB to fail fast
- Avoid reusing a per-request context for background operations; derive a background context for long-lived control ops
- Increase the handler deadline if opens legitimately take long
Example fix
// before err := store.EnableDB(ctx, path) // ctx already cancelled // after enableCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() err := store.EnableDB(enableCtx, path)
Defensive patterns
Strategy: retry
Validate before calling
if err := ctx.Err(); err != nil {
ctx = context.Background() // derive fresh context for control ops
} Try / catch
if err := store.EnableDB(ctx, path); err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
enableCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
return store.EnableDB(enableCtx, path)
}
return err
} Prevention
- Derive long-lived control contexts from context.Background, not request contexts
- Set generous deadlines for operations that trigger db.Open
- Check ctx.Err() before issuing store operations
When it happens
Trigger: Store.EnableDB(ctx, path) called with a cancelled or timed-out context — e.g. an IPC request whose deadline expired before reaching this point, or shutdown cancellation racing an enable.
Common situations: HTTP/IPC handlers with request deadlines that elapsed while waiting on the store lock; graceful shutdown cancelling in-flight control commands; a caller reusing an exhausted request context.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/384ef51656820d96.
Report an issue: GitHub.