diff --git a/server/apiv2/handlers/keyspace.go b/server/apiv2/handlers/keyspace.go
index 9602cc863ef..c2802bb939d 100644
--- a/server/apiv2/handlers/keyspace.go
+++ b/server/apiv2/handlers/keyspace.go
@@ -113,7 +113,7 @@ func LoadKeyspace(c *gin.Context) {
 	if value, ok := c.GetQuery("force_refresh_group_id"); ok && value == "true" {
 		groupManager := svr.GetKeyspaceGroupManager()
 		if groupManager == nil {
-			c.AbortWithStatusJSON(http.StatusInternalServerError, managerUninitializedErr)
+			c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 			return
 		}
 		// keyspace has been checked in LoadKeyspace, so no need to check again.
diff --git a/server/apiv2/handlers/tso_keyspace_group.go b/server/apiv2/handlers/tso_keyspace_group.go
index a580b21f705..a9f042687f6 100644
--- a/server/apiv2/handlers/tso_keyspace_group.go
+++ b/server/apiv2/handlers/tso_keyspace_group.go
@@ -30,7 +30,8 @@ import (
 	"github.com/tikv/pd/server/apiv2/middlewares"
 )
 
-const groupManagerUninitializedErr = "keyspace group manager is not initialized"
+// GroupManagerUninitializedErr is the error message for uninitialized keyspace group manager.
+const GroupManagerUninitializedErr = "keyspace group manager is not initialized"
 
 // RegisterTSOKeyspaceGroup registers keyspace group handlers to the server.
 func RegisterTSOKeyspaceGroup(r *gin.RouterGroup) {
@@ -78,7 +79,7 @@ func CreateKeyspaceGroups(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	err = manager.CreateKeyspaceGroups(createParams.KeyspaceGroups)
@@ -101,7 +102,7 @@ func GetKeyspaceGroups(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	keyspaceGroups, err := manager.GetKeyspaceGroups(scanStart, scanLimit)
@@ -152,7 +153,7 @@ func GetKeyspaceGroupByID(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 
@@ -189,7 +190,7 @@ func DeleteKeyspaceGroupByID(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	kg, err := manager.DeleteKeyspaceGroupByID(id)
@@ -250,7 +251,7 @@ func SplitKeyspaceGroupByID(c *gin.Context) {
 	}
 	groupManager := svr.GetKeyspaceGroupManager()
 	if groupManager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 
@@ -289,7 +290,7 @@ func FinishSplitKeyspaceByID(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	err = manager.FinishSplitKeyspaceByID(id)
@@ -337,7 +338,7 @@ func MergeKeyspaceGroups(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	groupManager := svr.GetKeyspaceGroupManager()
 	if groupManager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	// Merge keyspace group.
@@ -364,7 +365,7 @@ func FinishMergeKeyspaceByID(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	err = manager.FinishMergeKeyspaceByID(id)
@@ -390,7 +391,7 @@ func AllocNodesForKeyspaceGroup(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	allocParams := &AllocNodesForKeyspaceGroupParams{}
@@ -437,7 +438,7 @@ func SetNodesForKeyspaceGroup(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	setParams := &SetNodesForKeyspaceGroupParams{}
@@ -493,7 +494,7 @@ func SetPriorityForKeyspaceGroup(c *gin.Context) {
 	svr := c.MustGet(middlewares.ServerContextKey).(*server.Server)
 	manager := svr.GetKeyspaceGroupManager()
 	if manager == nil {
-		c.AbortWithStatusJSON(http.StatusInternalServerError, groupManagerUninitializedErr)
+		c.AbortWithStatusJSON(http.StatusInternalServerError, GroupManagerUninitializedErr)
 		return
 	}
 	setParams := &SetPriorityForKeyspaceGroupParams{}
diff --git a/tests/pdctl/keyspace/keyspace_test.go b/tests/pdctl/keyspace/keyspace_test.go
index 805a30e6f18..3ff755fe601 100644
--- a/tests/pdctl/keyspace/keyspace_test.go
+++ b/tests/pdctl/keyspace/keyspace_test.go
@@ -105,6 +105,35 @@ func TestKeyspace(t *testing.T) {
 	re.NoError(failpoint.Disable("github.com/tikv/pd/server/delayStartServerLoop"))
 }
 
+// Show command should auto retry without refresh_group_id if keyspace group manager not initialized.
+// See issue: #7441
+func TestKeyspaceGroupUninitialized(t *testing.T) {
+	re := require.New(t)
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+	re.NoError(failpoint.Enable("github.com/tikv/pd/server/delayStartServerLoop", `return(true)`))
+	re.NoError(failpoint.Enable("github.com/tikv/pd/pkg/keyspace/skipSplitRegion", "return(true)"))
+	tc, err := tests.NewTestCluster(ctx, 1)
+	re.NoError(err)
+	re.NoError(tc.RunInitialServers())
+	tc.WaitLeader()
+	re.NoError(tc.GetLeaderServer().BootstrapCluster())
+	pdAddr := tc.GetConfig().GetClientURL()
+
+	keyspaceName := "DEFAULT"
+	keyspaceID := uint32(0)
+	args := []string{"-u", pdAddr, "keyspace", "show", "name", keyspaceName}
+	output, err := pdctl.ExecuteCommand(pdctlCmd.GetRootCmd(), args...)
+	re.NoError(err)
+	var meta api.KeyspaceMeta
+	re.NoError(json.Unmarshal(output, &meta))
+	re.Equal(keyspaceName, meta.GetName())
+	re.Equal(keyspaceID, meta.GetId())
+
+	re.NoError(failpoint.Disable("github.com/tikv/pd/server/delayStartServerLoop"))
+	re.NoError(failpoint.Disable("github.com/tikv/pd/pkg/keyspace/skipSplitRegion"))
+}
+
 type keyspaceTestSuite struct {
 	suite.Suite
 	ctx     context.Context
diff --git a/tools/pd-ctl/pdctl/command/keyspace_command.go b/tools/pd-ctl/pdctl/command/keyspace_command.go
index 7c0d3d78bf6..93a99abc39f 100644
--- a/tools/pd-ctl/pdctl/command/keyspace_command.go
+++ b/tools/pd-ctl/pdctl/command/keyspace_command.go
@@ -28,11 +28,12 @@ import (
 const (
 	keyspacePrefix = "pd/api/v2/keyspaces"
 	// flags
-	nmConfig    = "config"
-	nmLimit     = "limit"
-	nmPageToken = "page_token"
-	nmRemove    = "remove"
-	nmUpdate    = "update"
+	nmConfig              = "config"
+	nmLimit               = "limit"
+	nmPageToken           = "page_token"
+	nmRemove              = "remove"
+	nmUpdate              = "update"
+	nmForceRefreshGroupID = "force_refresh_group_id"
 )
 
 // NewKeyspaceCommand returns a keyspace subcommand of rootCmd.
@@ -64,6 +65,7 @@ func newShowKeyspaceCommand() *cobra.Command {
 		Short: "show keyspace metadata specified by keyspace name",
 		Run:   showKeyspaceNameCommandFunc,
 	}
+	showByName.Flags().Bool(nmForceRefreshGroupID, true, "force refresh keyspace group id")
 	r.AddCommand(showByID)
 	r.AddCommand(showByName)
 	return r
@@ -87,7 +89,21 @@ func showKeyspaceNameCommandFunc(cmd *cobra.Command, args []string) {
 		cmd.Usage()
 		return
 	}
-	resp, err := doRequest(cmd, fmt.Sprintf("%s/%s?force_refresh_group_id=true", keyspacePrefix, args[0]), http.MethodGet, http.Header{})
+	refreshGroupID, err := cmd.Flags().GetBool(nmForceRefreshGroupID)
+	if err != nil {
+		cmd.PrintErrln("Failed to parse flag: ", err)
+		return
+	}
+	url := fmt.Sprintf("%s/%s", keyspacePrefix, args[0])
+	if refreshGroupID {
+		url += "?force_refresh_group_id=true"
+	}
+	resp, err := doRequest(cmd, url, http.MethodGet, http.Header{})
+	// Retry without the force_refresh_group_id if the keyspace group manager is not initialized.
+	// This can happen when PD is not running in API mode.
+	if err != nil && refreshGroupID && strings.Contains(err.Error(), handlers.GroupManagerUninitializedErr) {
+		resp, err = doRequest(cmd, fmt.Sprintf("%s/%s", keyspacePrefix, args[0]), http.MethodGet, http.Header{})
+	}
 	if err != nil {
 		cmd.PrintErrln("Failed to get the keyspace information: ", err)
 		return