benbjohnson/litestream · error
cannot access output path: %w
Error message
cannot access output path: %w
What it means
prepareOutputPath calls os.Stat on the requested restore output path and wraps any unexpected stat failure with this error. It means the OS could not stat the path for a reason other than non-existence — most commonly a permission problem on a parent directory or an I/O error. Non-existence is explicitly tolerated (restore will create the file), so this signals a real environmental problem.
Source
Thrown at cmd/litestream/restore.go:273
if opt.TXID != 0 {
return opt.TXID.String()
}
if opt.Follow {
return ""
}
infos, err := litestream.CalcRestorePlan(ctx, r.Client, opt.TXID, opt.Timestamp, r.Logger())
if err != nil || len(infos) == 0 {
return ""
}
return infos[len(infos)-1].MaxTXID.String()
}
func (c *RestoreCommand) prepareOutputPath(path string, force bool) error {
info, err := os.Stat(path)
if os.IsNotExist(err) {
return nil
} else if err != nil {
return fmt.Errorf("cannot access output path: %w", err)
}
if info.IsDir() {
return fmt.Errorf("cannot restore, output path is a directory: %s", path)
}
if info.Size() > 0 && !force {
return fmt.Errorf("cannot restore, output path already exists and is not empty: %s. Use -force to overwrite", path)
}
for _, sidecarPath := range []string{path + "-wal", path + "-shm", path + "-journal"} {
if _, err := os.Stat(sidecarPath); err == nil && !force {
return fmt.Errorf("cannot restore, SQLite sidecar path already exists: %s. Use -force to overwrite", sidecarPath)
} else if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot access SQLite sidecar path: %w", err)
}
}
for _, removePath := range []string{path, path + "-wal", path + "-shm", path + "-journal"} {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check permissions on every path component of the output path (ls -ld on each parent) and fix with chown/chmod
- Verify all intermediate path components are directories, not files
- Check `dmesg`/disk health if a filesystem error is suspected
- Run the restore as a user with access to the target location
Example fix
// before litestream restore -o /var/lib/db/app.db replica cannot access output path: stat /var/lib/db/app.db: permission denied // after sudo chown litestream:litestream /var/lib/db litestream restore -o /var/lib/db/app.db replica
Defensive patterns
Strategy: validation
Validate before calling
import "os"
import "path/filepath"
// Ensure the output location is statable and writable before restoring.
dir := filepath.Dir(outputPath)
if _, err := os.Stat(dir); err != nil {
return fmt.Errorf("output dir not accessible: %w", err)
}
f, err := os.CreateTemp(dir, ".restore-check")
if err != nil {
return fmt.Errorf("output dir not writable: %w", err)
}
f.Close()
os.Remove(f.Name()) Try / catch
if err := cmd.Run(ctx); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) {
return fmt.Errorf("check access to %s: %w", pe.Path, pe.Err)
}
return err
} Prevention
- Run litestream as a user with traverse/write access to the output directory
- Verify the full output path with `ls -ld` of each component before restoring
- Avoid paths containing non-directory components or dangling mounts
- Test output location writability with `touch <dir>/.probe` first
When it happens
Trigger: os.Stat(outputPath) returns an error that is not os.IsNotExist — e.g. a parent directory lacks search permission, the path component is not a directory, or an I/O error occurs while accessing the path.
Common situations: Restoring into a directory the current user cannot traverse (e.g. /var/lib owned by root); a typo'd path where a component is a file, not a directory; a dangling mount or full/EIO disk.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- cannot access SQLite sidecar path: %w
- remove existing output path: %w
- cannot restore, output path is a directory: %s
- cannot restore, output path already exists and is not empty:
- remove ltx directory: %w
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/6e6d87cea4bf840a.
Report an issue: GitHub.