benbjohnson/litestream · critical · LTXError
stage-mkdir
stage-mkdir
Error message
%w: %w (ErrDiskFull)
What it means
During WAL staging, creating the parent directory for the temporary LTX file failed with a disk-full condition. Litestream wraps it in an LTXError with code stage-mkdir so callers (including auto-recover logic) can classify it as ErrDiskFull.
Source
Thrown at db.go:2115
s.snapshotting = info.snapshotting
s.reason = info.reason
})
// Track total WAL bytes synced.
if sz > 0 {
db.totalWALBytesCounter.Add(float64(sz))
}
// Exit if we have no new WAL pages and we aren't snapshotting.
if !info.snapshotting && sz == 0 {
db.Logger.Log(ctx, internal.LevelTrace, "sync: skip", "reason", "no new wal pages")
return result, nil
}
tmpFilename := filename + ".tmp"
if err := internal.MkdirAll(filepath.Dir(tmpFilename), db.dirInfo); err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-mkdir", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, err
}
ltxFile, err := db.openLTXFile(tmpFilename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
if err != nil {
if isDiskFullError(err) {
return result, NewLTXError("stage-open", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf("%w: %w", ErrDiskFull, err))
}
return result, fmt.Errorf("open temp ltx file: %w", err)
}
defer func() { _ = os.Remove(tmpFilename) }()
defer func() { _ = ltxFile.Close() }()
uid, gid := internal.Fileinfo(db.fileInfo)
_ = os.Chown(tmpFilename, uid, gid)
db.Logger.Log(ctx, internal.LevelTrace, "encode header",View on GitHub (pinned to 4ed7a308f6)
Solutions
- Free space on the volume holding the staging/replica directory
- Point the Litestream data directory at a volume with headroom (config dir setting)
- Add monitoring/alerting on disk usage so ENOSPC is caught before syncs fail
- After freeing space, the next sync should succeed — no state reset needed
Example fix
// before $ df -h /var/lib/litestream # 100% used // after $ rm -rf /var/lib/litestream/tmp/* # or expand the volume df -h /var/lib/litestream # free space available, retry sync
Defensive patterns
Strategy: fallback
Validate before calling
usage, _ := syscall.Statfs(dir, &s) // check free space before staging
if s.Bavail*uint64(s.Bsize) < minFreeBytes { return errors.New("insufficient disk for staging") } Try / catch
var ltxErr *litestream.LTXError
if errors.As(err, <xErr) && errors.Is(ltxErr, litestream.ErrDiskFull) && ltxErr.Code == "stage-mkdir" {
alertOps("replica volume full: " + ltxErr.Filename)
} Prevention
- Alert on disk usage thresholds well before 100%
- Give the Litestream data directory a dedicated volume sized for WAL bursts
- Set container storage limits generously for staging workloads
When it happens
Trigger: internal.MkdirAll(filepath.Dir(tmpFilename)) fails with ENOSPC (detected via isDiskFullError) while creating <dbpath>-ltx staging directories.
Common situations: Volume hosting the Litestream replica/restore directory is full; large WAL growth after disk filled; container with a small ephemeral filesystem; quota exceeded.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/e492003346be64ae.
Report an issue: GitHub.