benbjohnson/litestream · error

cannot restore, output path already exists and is not empty:

Error message

cannot restore, output path already exists and is not empty: %s. Use -force to overwrite

What it means

prepareOutputPath refuses to overwrite an existing non-empty file at the output path unless -force is given. os.Stat found a regular file whose size is greater than zero and the force flag was false, so restore aborts to avoid silently destroying existing data.

Source

Thrown at cmd/litestream/restore.go:280

	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"} {
		if err := os.Remove(removePath); err != nil && !os.IsNotExist(err) {
			return fmt.Errorf("remove existing output path: %w", err)
		}
	}
	return nil
}

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Re-run the restore with -force to overwrite the existing file
  2. Delete or move the existing file, then re-run the restore
  3. Choose a different -o output path
  4. Verify the existing file isn't needed (e.g. it's the live DB of a running app) before forcing

Example fix

// before
litestream restore -o /data/app.db /path/to/db
cannot restore, output path already exists and is not empty: /data/app.db. Use -force to overwrite
// after
litestream restore -force -o /data/app.db /path/to/db
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(outputPath); err == nil && info.Size() > 0 && !forceFlag {
    return fmt.Errorf("%s exists; pass -force to overwrite", outputPath)
}

Try / catch

if err := cmd.Run(ctx); err != nil {
    if strings.Contains(err.Error(), "already exists and is not empty") {
        // decide: add -force or pick a new output path
    }
    return err
}

Prevention

When it happens

Trigger: Running `litestream restore -o <path>` where <path> exists as a non-empty regular file and no -force flag is passed.

Common situations: Re-running a restore into a location that already holds a database or leftover file; a partially written file from a previous failed run; CI reusing a workspace without cleaning artifacts; restoring over the live database path of a running application.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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