benbjohnson/litestream · critical

disk full

Error message

disk full

What it means

ErrDiskFull is litestream's sentinel error indicating the local disk ran out of space while replicating. It is wrapped into an LTXError with operation context (e.g. 'stage-mkdir') and is also matched against syscall.ENOSPC so OS-level 'no space left on device' errors are recognized. Because litestream stages WAL changes as LTX files on disk before upload, any filesystem write that exhausts space surfaces here.

Source

Thrown at litestream.go:37

const (
	MetaDirSuffix = "-litestream"
)

// SQLite checkpoint modes.
const (
	CheckpointModePassive  = "PASSIVE"
	CheckpointModeFull     = "FULL"
	CheckpointModeRestart  = "RESTART"
	CheckpointModeTruncate = "TRUNCATE"
)

// Litestream errors.
var (
	ErrNoSnapshots      = errors.New("no snapshots available")
	ErrChecksumMismatch = errors.New("invalid replica, checksum mismatch")
	ErrLTXCorrupted     = errors.New("ltx file corrupted")
	ErrLTXMissing       = errors.New("ltx file missing")
	ErrDiskFull         = errors.New("disk full")
)

// LTXError provides detailed context for LTX file errors with recovery hints.
type LTXError struct {
	Op      string // Operation that failed (e.g., "open", "read", "validate")
	Path    string // File path
	Level   int    // LTX level (0 = L0, etc.)
	MinTXID uint64 // Minimum transaction ID
	MaxTXID uint64 // Maximum transaction ID
	Err     error  // Underlying error
	Hint    string // Recovery hint for users
}

func (e *LTXError) Error() string {
	if e.Path != "" {
		return e.Op + " ltx file " + e.Path + ": " + e.Err.Error()
	}
	return e.Op + " ltx file: " + e.Err.Error()

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Free disk space on the filesystem containing the litestream staging directory (df -h, remove old logs/tmp files)
  2. Move the litestream working directory or staging path to a volume with sufficient headroom for peak WAL volume
  3. Add disk-space monitoring/alerting and automated cleanup of the staging area so ENOSPC never occurs mid-sync
  4. If the error came from a wrapped LTXError, check its Op/Path fields to find exactly which write failed and enlarge that location

Example fix

// before (ignoring disk state until failure)
if err := db.Sync(ctx); err != nil {
    log.Fatal(err)
}
// after
if err := db.Sync(ctx); err != nil {
    if errors.Is(err, litestream.ErrDiskFull) || errors.Is(err, syscall.ENOSPC) {
        freeSpaceOrHalt(db.Path()) // e.g. cleanup + alert before retrying
    }
    log.Fatal(err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

func hasDiskHeadroom(path string, need uint64) error {
    var st syscall.Statfs_t
    if err := syscall.Statfs(path, &st); err != nil {
        return err
    }
    avail := uint64(st.Bavail) * uint64(st.Bsize)
    if avail < need {
        return fmt.Errorf("only %d bytes free at %s", avail, path)
    }
    return nil
}

Type guard

func isDiskFull(err error) bool {
    return errors.Is(err, litestream.ErrDiskFull) || errors.Is(err, syscall.ENOSPC)
}

Try / catch

if err := db.Sync(ctx); err != nil {
    if isDiskFull(err) {
        alertAndFreeSpace(err) // page operator, clean staging dir, then retry
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: MkdirAll of the staging directory during LTX write (db.go:2115) fails with ENOSPC; other internal writes checked by isDiskFullError (db.go:1528) return ENOSPC or ErrDiskFull; the disk holding the litestream working/staging directory is full while syncing a transaction.

Common situations: Small disk or full partition on the host running litestream; tmpfs mount for the staging dir running out of space; a runaway database generating more WAL than disk can hold; quota-limited container filesystems.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/9d2ea1964372284a. Report an issue: GitHub.