diff --git a/cmd/dump_repo.go b/cmd/dump_repo.go
index c9d24c6c836..72456c61d33 100644
--- a/cmd/dump_repo.go
+++ b/cmd/dump_repo.go
@@ -7,6 +7,8 @@ package cmd
 import (
 	"context"
 	"errors"
+	"fmt"
+	"os"
 	"strings"
 
 	"code.gitea.io/gitea/modules/convert"
@@ -15,6 +17,7 @@ import (
 	base "code.gitea.io/gitea/modules/migration"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/services/migrations"
 
 	"github.com/urfave/cli"
@@ -159,9 +162,23 @@ func runDumpRepository(ctx *cli.Context) error {
 		}
 	}
 
+	// the repo_dir will be removed if error occurs in DumpRepository
+	// make sure the directory doesn't exist or is empty, prevent from deleting user files
+	repoDir := ctx.String("repo_dir")
+	if exists, err := util.IsExist(repoDir); err != nil {
+		return fmt.Errorf("unable to stat repo_dir %q: %v", repoDir, err)
+	} else if exists {
+		if isDir, _ := util.IsDir(repoDir); !isDir {
+			return fmt.Errorf("repo_dir %q already exists but it's not a directory", repoDir)
+		}
+		if dir, _ := os.ReadDir(repoDir); len(dir) > 0 {
+			return fmt.Errorf("repo_dir %q is not empty", repoDir)
+		}
+	}
+
 	if err := migrations.DumpRepository(
 		context.Background(),
-		ctx.String("repo_dir"),
+		repoDir,
 		ctx.String("owner_name"),
 		opts,
 	); err != nil {