diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index f4e2d7a9c0..012bbc9710 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -3572,6 +3572,7 @@ owner.settings.cargo.rebuild = Rebuild index
 owner.settings.cargo.rebuild.description = Rebuilding can be useful if the index is not synchronized with the stored Cargo packages.
 owner.settings.cargo.rebuild.error = Failed to rebuild Cargo index: %v
 owner.settings.cargo.rebuild.success = The Cargo index was successfully rebuild.
+owner.settings.cargo.rebuild.no_index = Cannot rebuild, no index is initialized.
 owner.settings.cleanuprules.title = Manage cleanup rules
 owner.settings.cleanuprules.add = Add cleanup rule
 owner.settings.cleanuprules.edit = Edit cleanup rule
diff --git a/routers/web/shared/packages/packages.go b/routers/web/shared/packages/packages.go
index 57671ad8f1..af960f1c0c 100644
--- a/routers/web/shared/packages/packages.go
+++ b/routers/web/shared/packages/packages.go
@@ -4,16 +4,19 @@
 package packages
 
 import (
+	"errors"
 	"fmt"
 	"net/http"
 	"time"
 
 	"code.gitea.io/gitea/models/db"
 	packages_model "code.gitea.io/gitea/models/packages"
+	repo_model "code.gitea.io/gitea/models/repo"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/base"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/optional"
+	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/services/context"
 	"code.gitea.io/gitea/services/forms"
@@ -29,6 +32,12 @@ func SetPackagesContext(ctx *context.Context, owner *user_model.User) {
 	}
 
 	ctx.Data["CleanupRules"] = pcrs
+
+	ctx.Data["CargoIndexExists"], err = repo_model.IsRepositoryModelExist(ctx, owner, cargo_service.IndexRepositoryName)
+	if err != nil {
+		ctx.ServerError("IsRepositoryModelExist", err)
+		return
+	}
 }
 
 func SetRuleAddContext(ctx *context.Context) {
@@ -240,7 +249,11 @@ func RebuildCargoIndex(ctx *context.Context, owner *user_model.User) {
 	err := cargo_service.RebuildIndex(ctx, owner, owner)
 	if err != nil {
 		log.Error("RebuildIndex failed: %v", err)
-		ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.error", err))
+		if errors.Is(err, util.ErrNotExist) {
+			ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.no_index"))
+		} else {
+			ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.error", err))
+		}
 	} else {
 		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cargo.rebuild.success"))
 	}
diff --git a/services/packages/cargo/index.go b/services/packages/cargo/index.go
index e8a8313625..59823cd3de 100644
--- a/services/packages/cargo/index.go
+++ b/services/packages/cargo/index.go
@@ -62,9 +62,9 @@ func InitializeIndexRepository(ctx context.Context, doer, owner *user_model.User
 }
 
 func RebuildIndex(ctx context.Context, doer, owner *user_model.User) error {
-	repo, err := getOrCreateIndexRepository(ctx, doer, owner)
+	repo, err := repo_model.GetRepositoryByOwnerAndName(ctx, owner.Name, IndexRepositoryName)
 	if err != nil {
-		return err
+		return fmt.Errorf("GetRepositoryByOwnerAndName: %w", err)
 	}
 
 	ps, err := packages_model.GetPackagesByType(ctx, owner.ID, packages_model.TypeCargo)
diff --git a/templates/package/shared/cargo.tmpl b/templates/package/shared/cargo.tmpl
index 401d909002..5b0f63965d 100644
--- a/templates/package/shared/cargo.tmpl
+++ b/templates/package/shared/cargo.tmpl
@@ -3,13 +3,7 @@
 </h4>
 <div class="ui attached segment">
 	<div class="ui form">
-		<div class="field">
-			<label>{{ctx.Locale.Tr "packages.owner.settings.cargo.initialize.description"}}</label>
-		</div>
-		<form class="field" action="{{.Link}}/cargo/initialize" method="post">
-			{{.CsrfTokenHtml}}
-			<button class="ui primary button">{{ctx.Locale.Tr "packages.owner.settings.cargo.initialize"}}</button>
-		</form>
+		{{if .CargoIndexExists}}
 		<div class="field">
 			<label>{{ctx.Locale.Tr "packages.owner.settings.cargo.rebuild.description"}}</label>
 		</div>
@@ -17,6 +11,15 @@
 			{{.CsrfTokenHtml}}
 			<button class="ui primary button">{{ctx.Locale.Tr "packages.owner.settings.cargo.rebuild"}}</button>
 		</form>
+		{{else}}
+		<div class="field">
+			<label>{{ctx.Locale.Tr "packages.owner.settings.cargo.initialize.description"}}</label>
+		</div>
+		<form class="field" action="{{.Link}}/cargo/initialize" method="post">
+			{{.CsrfTokenHtml}}
+			<button class="ui primary button">{{ctx.Locale.Tr "packages.owner.settings.cargo.initialize"}}</button>
+		</form>
+		{{end}}
 		<div class="field">
 			<label>{{ctx.Locale.Tr "packages.registry.documentation" "Cargo" "https://forgejo.org/docs/latest/user/packages/cargo/"}}</label>
 		</div>
diff --git a/tests/integration/api_packages_cargo_test.go b/tests/integration/api_packages_cargo_test.go
index c0705e0de5..869d90066a 100644
--- a/tests/integration/api_packages_cargo_test.go
+++ b/tests/integration/api_packages_cargo_test.go
@@ -23,6 +23,7 @@ import (
 	cargo_module "code.gitea.io/gitea/modules/packages/cargo"
 	"code.gitea.io/gitea/modules/setting"
 	cargo_router "code.gitea.io/gitea/routers/api/packages/cargo"
+	gitea_context "code.gitea.io/gitea/services/context"
 	cargo_service "code.gitea.io/gitea/services/packages/cargo"
 	"code.gitea.io/gitea/tests"
 
@@ -385,3 +386,62 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) {
 		assert.Equal(t, user.DisplayName(), owners.Users[0].Name)
 	})
 }
+
+func TestRebuildCargo(t *testing.T) {
+	onGiteaRun(t, func(t *testing.T, u *neturl.URL) {
+		user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+		session := loginUser(t, user.Name)
+		unittest.AssertExistsIf(t, false, &repo_model.Repository{OwnerID: user.ID, Name: cargo_service.IndexRepositoryName})
+
+		t.Run("No index", func(t *testing.T) {
+			defer tests.PrintCurrentTest(t)()
+
+			req := NewRequestWithValues(t, "POST", "/user/settings/packages/cargo/rebuild", map[string]string{
+				"_csrf": GetCSRF(t, session, "/user/settings/packages"),
+			})
+			session.MakeRequest(t, req, http.StatusSeeOther)
+
+			flashCookie := session.GetCookie(gitea_context.CookieNameFlash)
+			assert.NotNil(t, flashCookie)
+			assert.EqualValues(t, "error%3DCannot%2Brebuild%252C%2Bno%2Bindex%2Bis%2Binitialized.", flashCookie.Value)
+			unittest.AssertExistsIf(t, false, &repo_model.Repository{OwnerID: user.ID, Name: cargo_service.IndexRepositoryName})
+		})
+
+		t.Run("Initialize Cargo", func(t *testing.T) {
+			defer tests.PrintCurrentTest(t)()
+
+			req := NewRequest(t, "GET", "/user/settings/packages")
+			resp := session.MakeRequest(t, req, http.StatusOK)
+			htmlDoc := NewHTMLParser(t, resp.Body)
+
+			htmlDoc.AssertElement(t, `form[action="/user/settings/packages/cargo/rebuild"]`, false)
+			htmlDoc.AssertElement(t, `form[action="/user/settings/packages/cargo/initialize"]`, true)
+
+			req = NewRequestWithValues(t, "POST", "/user/settings/packages/cargo/initialize", map[string]string{
+				"_csrf": htmlDoc.GetCSRF(),
+			})
+			session.MakeRequest(t, req, http.StatusSeeOther)
+			unittest.AssertExistsIf(t, true, &repo_model.Repository{OwnerID: user.ID, Name: cargo_service.IndexRepositoryName})
+
+			req = NewRequest(t, "GET", "/user/settings/packages")
+			resp = session.MakeRequest(t, req, http.StatusOK)
+			htmlDoc = NewHTMLParser(t, resp.Body)
+
+			htmlDoc.AssertElement(t, `form[action="/user/settings/packages/cargo/rebuild"]`, true)
+			htmlDoc.AssertElement(t, `form[action="/user/settings/packages/cargo/initialize"]`, false)
+		})
+
+		t.Run("With index", func(t *testing.T) {
+			defer tests.PrintCurrentTest(t)()
+
+			req := NewRequestWithValues(t, "POST", "/user/settings/packages/cargo/rebuild", map[string]string{
+				"_csrf": GetCSRF(t, session, "/user/settings/packages"),
+			})
+			session.MakeRequest(t, req, http.StatusSeeOther)
+
+			flashCookie := session.GetCookie(gitea_context.CookieNameFlash)
+			assert.NotNil(t, flashCookie)
+			assert.EqualValues(t, "success%3DThe%2BCargo%2Bindex%2Bwas%2Bsuccessfully%2Brebuild.", flashCookie.Value)
+		})
+	})
+}