benbjohnson/litestream · error
remove L0 directory: %w
Error message
remove L0 directory: %w
What it means
When the database is behind the replica, Litestream clears the local L0 files by removing the level-0 LTX directory before re-fetching from the replica. This error wraps a failure of os.RemoveAll on that directory. It almost always indicates a filesystem-level problem (permissions, I/O error), since a missing directory is explicitly tolerated.
Source
Thrown at db.go:1616
if err != nil {
return fmt.Errorf("get replica position: %w", err)
} else if replicaInfo.MaxTXID == 0 {
return nil // No remote replica data yet
}
// Check if database is behind replica
if dbPos.TXID >= replicaInfo.MaxTXID {
return nil // Database is ahead or equal
}
db.Logger.Info("detected database behind replica",
"db_txid", dbPos.TXID,
"replica_txid", replicaInfo.MaxTXID)
// Clear local L0 files
l0Dir := db.LTXLevelDir(0)
if err := os.RemoveAll(l0Dir); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("remove L0 directory: %w", err)
}
db.invalidatePosCache()
if err := internal.MkdirAll(l0Dir, db.dirInfo); err != nil {
return fmt.Errorf("recreate L0 directory: %w", err)
}
// Fetch latest L0 LTX file from replica
minTXID, maxTXID := replicaInfo.MinTXID, replicaInfo.MaxTXID
reader, err := db.Replica.Client.OpenLTXFile(ctx, 0, minTXID, maxTXID, 0, 0)
if err != nil {
return fmt.Errorf("open remote L0 file: %w", err)
}
defer func() { _ = reader.Close() }()
// Write to temp file and atomically rename
localPath := db.LTXPath(0, minTXID, maxTXID)
tmpPath := localPath + ".tmp"
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check ownership/permissions of the L0 directory and that the litestream process user can write to it (ls -ld).
- Verify the volume is not mounted read-only (mount | grep, or container volume config).
- Look for processes holding files in the directory (lsof) and stop them (e.g. another litestream instance).
- Inspect the wrapped OS error (%w) for the exact errno; fix the underlying filesystem condition and let the next sync retry.
Example fix
// before: running litestream as wrong user $ litestream replicate -config /etc/litestream.yml // after: ensure data dir is writable by the service user $ chown -R litestream:litestream /var/lib/db && systemctl restart litestream
Defensive patterns
Strategy: validation
Validate before calling
// Ensure L0 dir is writable by the process user
info, err := os.Stat(l0Dir)
if err == nil && info.IsDir() {
if err := os.WriteFile(l0Dir+"/.probe", []byte("x"), 0o600); err != nil {
log.Fatalf("L0 dir not writable: %v", err)
}
os.Remove(l0Dir + "/.probe")
} Type guard
null
Try / catch
if err := os.RemoveAll(dir); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("remove L0 directory: %w", err)
} // inspect wrapped errno: EACCES -> chown, EROFS -> remount rw, EBUSY -> stop competing process Prevention
- Run litestream under a dedicated user owning the data dir
- Never mount the data volume read-only for the writer
- Ensure only one litestream instance manages a database
- Check container volume mount modes (rw, not ro)
When it happens
Trigger: checkDatabaseBehindReplica detects dbPos.TXID < replicaInfo.MaxTXID, calls os.RemoveAll(db.LTXLevelDir(0)), and the OS returns an error other than NotExist (e.g. EACCES, EBUSY, EIO).
Common situations: Litestream runs as a user without write permission on the LTX directory; the directory is mounted read-only; a file inside is held/immutable (or on Windows locked by another process); NFS/overlay filesystem I/O errors.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- recreate L0 directory: %w
- create temp L0 file: %w
- close L0 file: %w
- rename L0 file: %w
- read txid file: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/7dcbfd2d2a4f1264.
Report an issue: GitHub.