{"record":{"id":"e492003346be64ae","repo":"benbjohnson/litestream","slug":"stage-mkdir","errorCode":"stage-mkdir","errorMessage":"%w: %w (ErrDiskFull)","messagePattern":"%w: %w \\(ErrDiskFull\\)","errorType":"error_code","errorClass":"LTXError","httpStatus":null,"severity":"critical","filePath":"db.go","lineNumber":2115,"sourceCode":"\t\t\ts.snapshotting = info.snapshotting\n\t\t\ts.reason = info.reason\n\t\t})\n\n\t// Track total WAL bytes synced.\n\tif sz > 0 {\n\t\tdb.totalWALBytesCounter.Add(float64(sz))\n\t}\n\n\t// Exit if we have no new WAL pages and we aren't snapshotting.\n\tif !info.snapshotting && sz == 0 {\n\t\tdb.Logger.Log(ctx, internal.LevelTrace, \"sync: skip\", \"reason\", \"no new wal pages\")\n\t\treturn result, nil\n\t}\n\n\ttmpFilename := filename + \".tmp\"\n\tif err := internal.MkdirAll(filepath.Dir(tmpFilename), db.dirInfo); err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-mkdir\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, err\n\t}\n\n\tltxFile, err := db.openLTXFile(tmpFilename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)\n\tif err != nil {\n\t\tif isDiskFullError(err) {\n\t\t\treturn result, NewLTXError(\"stage-open\", tmpFilename, 0, uint64(txID), uint64(txID), fmt.Errorf(\"%w: %w\", ErrDiskFull, err))\n\t\t}\n\t\treturn result, fmt.Errorf(\"open temp ltx file: %w\", err)\n\t}\n\tdefer func() { _ = os.Remove(tmpFilename) }()\n\tdefer func() { _ = ltxFile.Close() }()\n\n\tuid, gid := internal.Fileinfo(db.fileInfo)\n\t_ = os.Chown(tmpFilename, uid, gid)\n\n\tdb.Logger.Log(ctx, internal.LevelTrace, \"encode header\",","sourceCodeStart":2097,"sourceCodeEnd":2133,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L2097-L2133","documentation":"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.","triggerScenarios":"internal.MkdirAll(filepath.Dir(tmpFilename)) fails with ENOSPC (detected via isDiskFullError) while creating <dbpath>-ltx staging directories.","commonSituations":"Volume hosting the Litestream replica/restore directory is full; large WAL growth after disk filled; container with a small ephemeral filesystem; quota exceeded.","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"],"exampleFix":"// before\n$ df -h /var/lib/litestream  # 100% used\n// after\n$ rm -rf /var/lib/litestream/tmp/*  # or expand the volume\ndf -h /var/lib/litestream            # free space available, retry sync","handlingStrategy":"fallback","validationCode":"usage, _ := syscall.Statfs(dir, &s) // check free space before staging\nif s.Bavail*uint64(s.Bsize) < minFreeBytes { return errors.New(\"insufficient disk for staging\") }","typeGuard":null,"tryCatchPattern":"var ltxErr *litestream.LTXError\nif errors.As(err, &ltxErr) && errors.Is(ltxErr, litestream.ErrDiskFull) && ltxErr.Code == \"stage-mkdir\" {\n\talertOps(\"replica volume full: \" + ltxErr.Filename)\n}","preventionTips":["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"],"tags":["disk-full","filesystem","staging"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}