From 3a7d7bdecd08d13876a05136ef2f38ffd7d55175 Mon Sep 17 00:00:00 2001
From: Pavel Karpy <carpawell@nspcc.ru>
Date: Tue, 6 Jul 2021 15:27:54 +0300
Subject: [PATCH] [#665] cli: Set non-zero exit codes in `err` cases

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
---
 cmd/neofs-cli/modules/accounting.go   |  25 +--
 cmd/neofs-cli/modules/container.go    | 244 ++++++--------------------
 cmd/neofs-cli/modules/control.go      | 171 +++++++-----------
 cmd/neofs-cli/modules/netmap.go       |  46 +----
 cmd/neofs-cli/modules/object.go       | 242 ++++++-------------------
 cmd/neofs-cli/modules/root.go         |  10 +-
 cmd/neofs-cli/modules/storagegroup.go | 140 ++++-----------
 cmd/neofs-cli/modules/util.go         | 109 +++---------
 8 files changed, 245 insertions(+), 742 deletions(-)

diff --git a/cmd/neofs-cli/modules/accounting.go b/cmd/neofs-cli/modules/accounting.go
index eb5448982..ba88d8a76 100644
--- a/cmd/neofs-cli/modules/accounting.go
+++ b/cmd/neofs-cli/modules/accounting.go
@@ -34,38 +34,23 @@ var accountingBalanceCmd = &cobra.Command{
 		)
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		if balanceOwner == "" {
 			wallet, err := owner.NEO3WalletFromPublicKey(&key.PublicKey)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			oid = owner.NewIDFromNeo3Wallet(wallet)
 		} else {
 			oid, err = ownerFromString(balanceOwner)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 		}
 
 		response, err = cli.GetBalance(ctx, oid, globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		// print to stdout
 		prettyPrintDecimal(cmd, response)
diff --git a/cmd/neofs-cli/modules/container.go b/cmd/neofs-cli/modules/container.go
index 95152af06..eb23611e7 100644
--- a/cmd/neofs-cli/modules/container.go
+++ b/cmd/neofs-cli/modules/container.go
@@ -67,6 +67,12 @@ var (
 	eaclPathFrom string
 )
 
+var (
+	errDeleteTimeout  = errors.New("timeout: container has not been removed from sidechain")
+	errCreateTimeout  = errors.New("timeout: container has not been persisted on sidechain")
+	errSetEACLTimeout = errors.New("timeout: EACL has not been persisted on sidechain")
+)
+
 // containerCmd represents the container command
 var containerCmd = &cobra.Command{
 	Use:   "container",
@@ -87,38 +93,23 @@ var listContainersCmd = &cobra.Command{
 		)
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		if containerOwner == "" {
 			wallet, err := owner.NEO3WalletFromPublicKey(&key.PublicKey)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			oid = owner.NewIDFromNeo3Wallet(wallet)
 		} else {
 			oid, err = ownerFromString(containerOwner)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 		}
 
 		response, err = cli.ListContainers(ctx, oid, globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		// print to stdout
 		prettyPrintContainerList(cmd, response)
@@ -134,46 +125,25 @@ It will be stored in sidechain when inner ring will accepts it.`,
 		ctx := context.Background()
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		placementPolicy, err := parseContainerPolicy(containerPolicy)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		attributes, err := parseAttributes(containerAttributes)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		basicACL, err := parseBasicACL(containerACL)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		nonce, err := parseNonce(containerNonce)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		tok, err := getSessionToken(sessionTokenPath)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cnr := container.New()
 		cnr.SetPlacementPolicy(placementPolicy)
@@ -184,10 +154,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
 		cnr.SetOwnerID(tok.OwnerID())
 
 		id, err := cli.PutContainer(ctx, cnr, globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		cmd.Println("container ID:", id)
 
@@ -204,7 +171,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
 				}
 			}
 
-			cmd.PrintErrln("timeout: container has not been persisted on sidechain")
+			exitOnErr(cmd, errCreateTimeout)
 		}
 	},
 }
@@ -218,28 +185,16 @@ Only owner of the container has a permission to remove container.`,
 		ctx := context.Background()
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		id, err := parseContainerID(containerID)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		tok, err := getSessionToken(sessionTokenPath)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		callOpts := globalCallOptions()
 
@@ -248,10 +203,7 @@ Only owner of the container has a permission to remove container.`,
 		}
 
 		err = cli.DeleteContainer(ctx, id, callOpts...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		cmd.Println("container delete method invoked")
 
@@ -268,7 +220,7 @@ Only owner of the container has a permission to remove container.`,
 				}
 			}
 
-			cmd.PrintErrln("timeout: container has not been removed from sidechain")
+			exitOnErr(cmd, errDeleteTimeout)
 		}
 	},
 }
@@ -281,28 +233,16 @@ var listContainerObjectsCmd = &cobra.Command{
 		ctx := context.Background()
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		id, err := parseContainerID(containerID)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		sessionToken, err := cli.CreateSession(ctx, math.MaxUint64)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't create session token: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("can't create session token: %w", err))
 
 		filters := new(object.SearchFilters)
 		filters.AddRootFilter() // search only user created objects
@@ -316,10 +256,7 @@ var listContainerObjectsCmd = &cobra.Command{
 				client.WithSession(sessionToken),
 			)...,
 		)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		for i := range objectIDs {
 			cmd.Println(objectIDs[i])
@@ -340,40 +277,23 @@ var getContainerInfoCmd = &cobra.Command{
 
 		if containerPathFrom != "" {
 			data, err := os.ReadFile(containerPathFrom)
-			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("can't read file: %w", err))
-				return
-			}
+			exitOnErr(cmd, errf("can't read file: %w", err))
 
 			cnr = container.New()
-			if err := cnr.Unmarshal(data); err != nil {
-				cmd.PrintErrln(fmt.Errorf("can't unmarshal container: %w", err))
-				return
-			}
+			err = cnr.Unmarshal(data)
+			exitOnErr(cmd, errf("can't unmarshal container: %w", err))
 		} else {
 			key, err := getKey()
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			cli, err := getSDKClient(key)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			id, err := parseContainerID(containerID)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			cnr, err = cli.GetContainer(ctx, id, globalCallOptions()...)
-			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-				return
-			}
+			exitOnErr(cmd, errf("rpc error: %w", err))
 		}
 
 		prettyPrintContainer(cmd, cnr, containerJSON)
@@ -386,23 +306,14 @@ var getContainerInfoCmd = &cobra.Command{
 
 			if containerJSON {
 				data, err = cnr.MarshalJSON()
-				if err != nil {
-					cmd.PrintErrln(fmt.Errorf("can't JSON encode container: %w", err))
-					return
-				}
+				exitOnErr(cmd, errf("can't JSON encode container: %w", err))
 			} else {
 				data, err = cnr.Marshal()
-				if err != nil {
-					cmd.PrintErrln(fmt.Errorf("can't binary encode container: %w", err))
-					return
-				}
+				exitOnErr(cmd, errf("can't binary encode container: %w", err))
 			}
 
 			err = os.WriteFile(containerPathTo, data, 0644)
-			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("can't write container to file: %w", err))
-				return
-			}
+			exitOnErr(cmd, errf("can't write container to file: %w", err))
 		}
 	},
 }
@@ -415,28 +326,16 @@ var getExtendedACLCmd = &cobra.Command{
 		ctx := context.Background()
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		id, err := parseContainerID(containerID)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		res, err := cli.GetEACL(ctx, id, globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		eaclTable := res.EACL()
 		sig := eaclTable.Signature()
@@ -455,16 +354,10 @@ var getExtendedACLCmd = &cobra.Command{
 
 		if containerJSON {
 			data, err = eaclTable.MarshalJSON()
-			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("can't enode to JSON: %w", err))
-				return
-			}
+			exitOnErr(cmd, errf("can't enode to JSON: %w", err))
 		} else {
 			data, err = eaclTable.Marshal()
-			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("can't enode to binary: %w", err))
-				return
-			}
+			exitOnErr(cmd, errf("can't enode to binary: %w", err))
 		}
 
 		cmd.Println("dumping data to file:", containerPathTo)
@@ -472,9 +365,8 @@ var getExtendedACLCmd = &cobra.Command{
 		cmd.Println("Signature:")
 		printJSONMarshaler(cmd, sig, "signature")
 
-		if err = os.WriteFile(containerPathTo, data, 0644); err != nil {
-			cmd.PrintErrln(err)
-		}
+		err = os.WriteFile(containerPathTo, data, 0644)
+		exitOnErr(cmd, err)
 	},
 }
 
@@ -487,50 +379,29 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
 		ctx := context.Background()
 
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		id, err := parseContainerID(containerID)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		eaclTable, err := parseEACL(eaclPathFrom)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		tok, err := getSessionToken(sessionTokenPath)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		eaclTable.SetCID(id)
 		eaclTable.SetSessionToken(tok)
 
 		err = cli.SetEACL(ctx, eaclTable, globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		if containerAwait {
 			exp, err := eaclTable.Marshal()
-			if err != nil {
-				cmd.PrintErrln("broken EACL table")
-				return
-			}
+			exitOnErr(cmd, errf("broken EACL table: %w", err))
 
 			cmd.Println("awaiting...")
 
@@ -552,8 +423,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
 				}
 			}
 
-			cmd.PrintErrln("timeout: EACL has not been persisted on sidechain")
-			return
+			exitOnErr(cmd, errSetEACLTimeout)
 		}
 	},
 }
diff --git a/cmd/neofs-cli/modules/control.go b/cmd/neofs-cli/modules/control.go
index 692c275ab..46b726e47 100644
--- a/cmd/neofs-cli/modules/control.go
+++ b/cmd/neofs-cli/modules/control.go
@@ -85,16 +85,10 @@ func init() {
 
 func healthCheck(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	cli, err := getSDKClient(key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	if healthCheckIRVar {
 		healthCheckIR(cmd, key, cli)
@@ -105,25 +99,21 @@ func healthCheck(cmd *cobra.Command, _ []string) {
 
 	req.SetBody(new(control.HealthCheckRequest_Body))
 
-	if err := controlSvc.SignMessage(key, req); err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	err = controlSvc.SignMessage(key, req)
+	exitOnErr(cmd, err)
 
 	resp, err := control.HealthCheck(cli.Raw(), req)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	sign := resp.GetSignature()
 
-	if err := signature.VerifyDataWithSource(resp, func() ([]byte, []byte) {
-		return sign.GetKey(), sign.GetSign()
-	}); err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	err = signature.VerifyDataWithSource(
+		resp,
+		func() ([]byte, []byte) {
+			return sign.GetKey(), sign.GetSign()
+		},
+	)
+	exitOnErr(cmd, err)
 
 	cmd.Printf("Network status: %s\n", resp.GetBody().GetNetmapStatus())
 	cmd.Printf("Health status: %s\n", resp.GetBody().GetHealthStatus())
@@ -134,42 +124,34 @@ func healthCheckIR(cmd *cobra.Command, key *ecdsa.PrivateKey, c client.Client) {
 
 	req.SetBody(new(ircontrol.HealthCheckRequest_Body))
 
-	if err := ircontrolsrv.SignMessage(key, req); err != nil {
-		cmd.PrintErrln(fmt.Errorf("could not sign request: %w", err))
-		return
-	}
+	err := ircontrolsrv.SignMessage(key, req)
+	exitOnErr(cmd, errf("could not sign request: %w", err))
 
 	resp, err := ircontrol.HealthCheck(c.Raw(), req)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("rpc failure: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("rpc failure: %w", err))
 
 	sign := resp.GetSignature()
 
-	if err := signature.VerifyDataWithSource(resp, func() ([]byte, []byte) {
-		return sign.GetKey(), sign.GetSign()
-	}); err != nil {
-		cmd.PrintErrln(fmt.Errorf("invalid response signature: %w", err))
-		return
-	}
+	err = signature.VerifyDataWithSource(
+		resp,
+		func() ([]byte, []byte) {
+			return sign.GetKey(), sign.GetSign()
+		},
+	)
+	exitOnErr(cmd, errf("invalid response signature: %w", err))
 
 	cmd.Printf("Health status: %s\n", resp.GetBody().GetHealthStatus())
 }
 
 func setNetmapStatus(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	var status control.NetmapStatus
 
 	switch netmapStatus {
 	default:
-		cmd.PrintErrln(fmt.Errorf("unsupported status %s", netmapStatus))
-		return
+		exitOnErr(cmd, fmt.Errorf("unsupported status %s", netmapStatus))
 	case netmapStatusOnline:
 		status = control.NetmapStatus_ONLINE
 	case netmapStatusOffline:
@@ -183,31 +165,24 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) {
 
 	body.SetStatus(status)
 
-	if err := controlSvc.SignMessage(key, req); err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	err = controlSvc.SignMessage(key, req)
+	exitOnErr(cmd, err)
 
 	cli, err := getSDKClient(key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	resp, err := control.SetNetmapStatus(cli.Raw(), req)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	sign := resp.GetSignature()
 
-	if err := signature.VerifyDataWithSource(resp, func() ([]byte, []byte) {
-		return sign.GetKey(), sign.GetSign()
-	}); err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	err = signature.VerifyDataWithSource(
+		resp,
+		func() ([]byte, []byte) {
+			return sign.GetKey(), sign.GetSign()
+		},
+	)
+	exitOnErr(cmd, err)
 
 	cmd.Println("Network status update request successfully sent.")
 }
@@ -222,10 +197,7 @@ var dropObjectsCmd = &cobra.Command{
 	Long:  "Drop objects from the node's local storage",
 	Run: func(cmd *cobra.Command, args []string) {
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		binAddrList := make([][]byte, 0, len(dropObjectsList))
 
@@ -234,15 +206,11 @@ var dropObjectsCmd = &cobra.Command{
 
 			err := a.Parse(dropObjectsList[i])
 			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("could not parse address #%d: %w", i, err))
-				return
+				exitOnErr(cmd, fmt.Errorf("could not parse address #%d: %w", i, err))
 			}
 
 			binAddr, err := a.Marshal()
-			if err != nil {
-				cmd.PrintErrln(fmt.Errorf("could not marshal the address: %w", err))
-				return
-			}
+			exitOnErr(cmd, errf("could not marshal the address: %w", err))
 
 			binAddrList = append(binAddrList, binAddr)
 		}
@@ -254,31 +222,24 @@ var dropObjectsCmd = &cobra.Command{
 
 		body.SetAddressList(binAddrList)
 
-		if err := controlSvc.SignMessage(key, req); err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		err = controlSvc.SignMessage(key, req)
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		resp, err := control.DropObjects(cli.Raw(), req)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		sign := resp.GetSignature()
 
-		if err := signature.VerifyDataWithSource(resp, func() ([]byte, []byte) {
-			return sign.GetKey(), sign.GetSign()
-		}); err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		err = signature.VerifyDataWithSource(
+			resp,
+			func() ([]byte, []byte) {
+				return sign.GetKey(), sign.GetSign()
+			},
+		)
+		exitOnErr(cmd, err)
 
 		cmd.Println("Objects were successfully marked to be removed.")
 	},
@@ -290,39 +251,29 @@ var snapshotCmd = &cobra.Command{
 	Long:  "Get network map snapshot",
 	Run: func(cmd *cobra.Command, args []string) {
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		req := new(control.NetmapSnapshotRequest)
 		req.SetBody(new(control.NetmapSnapshotRequest_Body))
 
-		if err := controlSvc.SignMessage(key, req); err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		err = controlSvc.SignMessage(key, req)
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		resp, err := control.NetmapSnapshot(cli.Raw(), req)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		sign := resp.GetSignature()
 
-		if err := signature.VerifyDataWithSource(resp, func() ([]byte, []byte) {
-			return sign.GetKey(), sign.GetSign()
-		}); err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		err = signature.VerifyDataWithSource(
+			resp,
+			func() ([]byte, []byte) {
+				return sign.GetKey(), sign.GetSign()
+			},
+		)
+		exitOnErr(cmd, err)
 
 		prettyPrintNetmap(cmd, resp.GetBody().GetNetmap(), netmapSnapshotJSON)
 	},
diff --git a/cmd/neofs-cli/modules/netmap.go b/cmd/neofs-cli/modules/netmap.go
index 1ec9d8be5..1be83c6a9 100644
--- a/cmd/neofs-cli/modules/netmap.go
+++ b/cmd/neofs-cli/modules/netmap.go
@@ -3,7 +3,6 @@ package cmd
 import (
 	"context"
 	"encoding/hex"
-	"fmt"
 
 	"github.com/mr-tron/base58"
 	"github.com/nspcc-dev/neo-go/pkg/config/netmode"
@@ -43,22 +42,13 @@ var getEpochCmd = &cobra.Command{
 	Long:  "Get current epoch number",
 	Run: func(cmd *cobra.Command, args []string) {
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		netInfo, err := cli.NetworkInfo(context.Background(), globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		cmd.Println(netInfo.CurrentEpoch())
 	},
@@ -70,22 +60,13 @@ var localNodeInfoCmd = &cobra.Command{
 	Long:  `Get local node info`,
 	Run: func(cmd *cobra.Command, args []string) {
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		nodeInfo, err := cli.EndpointInfo(context.Background(), globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		prettyPrintNodeInfo(cmd, nodeInfo.NodeInfo(), nodeInfoJSON)
 	},
@@ -97,22 +78,13 @@ var netInfoCmd = &cobra.Command{
 	Long:  "Get information about NeoFS network",
 	Run: func(cmd *cobra.Command, args []string) {
 		key, err := getKey()
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		cli, err := getSDKClient(key)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 
 		netInfo, err := cli.NetworkInfo(context.Background(), globalCallOptions()...)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("rpc error: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("rpc error: %w", err))
 
 		cmd.Printf("Epoch: %d\n", netInfo.CurrentEpoch())
 
diff --git a/cmd/neofs-cli/modules/object.go b/cmd/neofs-cli/modules/object.go
index d020f5ed6..8ad1e0ff2 100644
--- a/cmd/neofs-cli/modules/object.go
+++ b/cmd/neofs-cli/modules/object.go
@@ -208,34 +208,21 @@ func initSession(ctx context.Context, key *ecdsa.PrivateKey) (client.Client, *se
 
 func putObject(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	ownerID, err := getOwnerID(key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	cid, err := getCID(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	filename := cmd.Flag("file").Value.String()
 	f, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
 	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't open file '%s': %w", filename, err))
-		return
+		exitOnErr(cmd, fmt.Errorf("can't open file '%s': %w", filename, err))
 	}
 
 	attrs, err := parseObjectAttrs(cmd)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't parse object attributes: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't parse object attributes: %w", err))
 
 	expiresOn, _ := cmd.Flags().GetUint64(putExpiresOnFlag)
 	if expiresOn > 0 {
@@ -264,15 +251,9 @@ func putObject(cmd *cobra.Command, _ []string) {
 
 	ctx := context.Background()
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	btok, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	oid, err := cli.PutObject(ctx,
 		new(client.PutObjectParams).
 			WithObject(obj.Object()).
@@ -282,10 +263,7 @@ func putObject(cmd *cobra.Command, _ []string) {
 			client.WithBearer(btok),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't put object: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't put object: %w", err))
 
 	cmd.Printf("[%s] Object successfully stored\n", filename)
 	cmd.Printf("  ID: %s\n  CID: %s\n", oid, cid)
@@ -293,28 +271,16 @@ func putObject(cmd *cobra.Command, _ []string) {
 
 func deleteObject(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	objAddr, err := getObjectAddress(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	btok, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	tombstoneAddr, err := client.DeleteObject(ctx, cli,
 		new(client.DeleteObjectParams).WithAddress(objAddr),
@@ -323,10 +289,7 @@ func deleteObject(cmd *cobra.Command, _ []string) {
 			client.WithBearer(btok),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	cmd.Println("Object removed successfully.")
 	cmd.Printf("  ID: %s\n  CID: %s\n", tombstoneAddr.ObjectID(), tombstoneAddr.ContainerID())
@@ -334,16 +297,10 @@ func deleteObject(cmd *cobra.Command, _ []string) {
 
 func getObject(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	objAddr, err := getObjectAddress(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	var out io.Writer
 	filename := cmd.Flag("file").Value.String()
@@ -352,24 +309,19 @@ func getObject(cmd *cobra.Command, _ []string) {
 	} else {
 		f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, os.ModePerm)
 		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't open file '%s': %w", filename, err))
-			return
+			exitOnErr(cmd, fmt.Errorf("can't open file '%s': %w", filename, err))
 		}
+
 		defer f.Close()
+
 		out = f
 	}
 
 	ctx := context.Background()
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	btok, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	raw, _ := cmd.Flags().GetBool(rawFlag)
 
@@ -388,8 +340,7 @@ func getObject(cmd *cobra.Command, _ []string) {
 			return
 		}
 
-		cmd.PrintErrln(fmt.Errorf("can't get object: %w", err))
-		return
+		exitOnErr(cmd, fmt.Errorf("can't get object: %w", err))
 	}
 
 	if filename != "" {
@@ -399,37 +350,23 @@ func getObject(cmd *cobra.Command, _ []string) {
 	// Print header only if file is not streamed to stdout.
 	hdrFile := cmd.Flag("header").Value.String()
 	if filename != "" || hdrFile != "" {
-		if err = saveAndPrintHeader(cmd, obj, hdrFile); err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		err = saveAndPrintHeader(cmd, obj, hdrFile)
+		exitOnErr(cmd, err)
 	}
 }
 
 func getObjectHeader(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	objAddr, err := getObjectAddress(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	btok, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	ps := new(client.ObjectHeaderParams).WithAddress(objAddr)
 	if ok, _ := cmd.Flags().GetBool("main-only"); ok {
 		ps = ps.WithMainFields()
@@ -449,46 +386,28 @@ func getObjectHeader(cmd *cobra.Command, _ []string) {
 			return
 		}
 
-		cmd.PrintErrln(fmt.Errorf("can't get object header: %w", err))
-		return
+		exitOnErr(cmd, fmt.Errorf("can't get object header: %w", err))
 	}
 
-	if err = saveAndPrintHeader(cmd, obj, cmd.Flag("file").Value.String()); err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	err = saveAndPrintHeader(cmd, obj, cmd.Flag("file").Value.String())
+	exitOnErr(cmd, err)
 }
 
 func searchObject(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	cid, err := getCID(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	sf, err := parseSearchFilters(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	btok, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	ps := new(client.SearchObjectParams).WithContainerID(cid).WithSearchFilters(sf)
 	ids, err := cli.SearchObject(ctx, ps,
 		append(globalCallOptions(),
@@ -496,10 +415,7 @@ func searchObject(cmd *cobra.Command, _ []string) {
 			client.WithBearer(btok),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't search object: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't search object: %w", err))
 	cmd.Printf("Found %d objects.\n", len(ids))
 	for _, id := range ids {
 		cmd.Println(id)
@@ -508,46 +424,25 @@ func searchObject(cmd *cobra.Command, _ []string) {
 
 func getObjectHash(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	objAddr, err := getObjectAddress(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	ranges, err := getRangeList(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	typ, err := getHashType(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	strSalt := strings.TrimPrefix(cmd.Flag(getRangeHashSaltFlag).Value.String(), "0x")
 
 	salt, err := hex.DecodeString(strSalt)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	btok, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 	if len(ranges) == 0 { // hash of full payload
 		obj, err := cli.GetObjectHeader(ctx,
 			new(client.ObjectHeaderParams).WithAddress(objAddr),
@@ -556,10 +451,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
 				client.WithBearer(btok),
 			)...,
 		)
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't get object header: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("can't get object header: %w", err))
 		switch typ {
 		case hashSha256:
 			cmd.Println(hex.EncodeToString(obj.PayloadChecksum().Sum()))
@@ -582,10 +474,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
 				client.WithBearer(btok),
 			)...,
 		)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 		for i := range res {
 			cmd.Printf("Offset=%d (Length=%d)\t: %s\n", ranges[i].GetOffset(), ranges[i].GetLength(),
 				hex.EncodeToString(res[i][:]))
@@ -597,10 +486,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
 				client.WithBearer(btok),
 			)...,
 		)
-		if err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+		exitOnErr(cmd, err)
 		for i := range res {
 			cmd.Printf("Offset=%d (Length=%d)\t: %s\n", ranges[i].GetOffset(), ranges[i].GetLength(),
 				hex.EncodeToString(res[i][:]))
@@ -926,24 +812,16 @@ func getBearerToken(cmd *cobra.Command, flagname string) (*token.BearerToken, er
 
 func getObjectRange(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	objAddr, err := getObjectAddress(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ranges, err := getRangeList(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	} else if len(ranges) != 1 {
-		cmd.PrintErrln(err)
-		return
+	exitOnErr(cmd, err)
+
+	if len(ranges) != 1 {
+		exitOnErr(cmd, fmt.Errorf("exactly one range must be specified, got: %d", len(ranges)))
 	}
 
 	var out io.Writer
@@ -954,8 +832,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
 	} else {
 		f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, os.ModePerm)
 		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't open file '%s': %w", filename, err))
-			return
+			exitOnErr(cmd, fmt.Errorf("can't open file '%s': %w", filename, err))
 		}
 
 		defer f.Close()
@@ -966,16 +843,10 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
 	ctx := context.Background()
 
 	c, sessionToken, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	bearerToken, err := getBearerToken(cmd, "bearer")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	raw, _ := cmd.Flags().GetBool(rawFlag)
 
@@ -995,8 +866,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
 			return
 		}
 
-		cmd.PrintErrln(fmt.Errorf("can't get object payload range: %w", err))
-		return
+		exitOnErr(cmd, fmt.Errorf("can't get object payload range: %w", err))
 	}
 
 	if filename != "" {
diff --git a/cmd/neofs-cli/modules/root.go b/cmd/neofs-cli/modules/root.go
index 2fcaeb866..60a95b1ff 100644
--- a/cmd/neofs-cli/modules/root.go
+++ b/cmd/neofs-cli/modules/root.go
@@ -63,9 +63,8 @@ var (
 // Execute adds all child commands to the root command and sets flags appropriately.
 // This is called by main.main(). It only needs to happen once to the rootCmd.
 func Execute() {
-	if err := rootCmd.Execute(); err != nil {
-		os.Exit(1)
-	}
+	err := rootCmd.Execute()
+	exitOnErr(rootCmd, err)
 }
 
 func init() {
@@ -136,10 +135,7 @@ func initConfig() {
 	} else {
 		// Find home directory.
 		home, err := homedir.Dir()
-		if err != nil {
-			fmt.Println(err)
-			os.Exit(1)
-		}
+		exitOnErr(rootCmd, err)
 
 		// Search config in `$HOME/.config/neofs-cli/` with name "config.yaml"
 		viper.AddConfigPath(filepath.Join(home, ".config", "neofs-cli"))
diff --git a/cmd/neofs-cli/modules/storagegroup.go b/cmd/neofs-cli/modules/storagegroup.go
index b1aae7869..2b283a517 100644
--- a/cmd/neofs-cli/modules/storagegroup.go
+++ b/cmd/neofs-cli/modules/storagegroup.go
@@ -3,7 +3,6 @@ package cmd
 import (
 	"context"
 	"errors"
-	"fmt"
 
 	"github.com/nspcc-dev/neofs-api-go/pkg/client"
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
@@ -129,48 +128,32 @@ func sgBearerToken(cmd *cobra.Command) (*token.BearerToken, error) {
 
 func putSG(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	ownerID, err := getOwnerID(key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	cid, err := getCID(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	members := make([]*objectSDK.ID, 0, len(sgMembers))
 
 	for i := range sgMembers {
 		id := objectSDK.NewID()
-		if err := id.Parse(sgMembers[i]); err != nil {
-			cmd.PrintErrln(err)
-			return
-		}
+
+		err = id.Parse(sgMembers[i])
+		exitOnErr(cmd, err)
 
 		members = append(members, id)
 	}
 
 	bearerToken, err := sgBearerToken(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	sg, err := storagegroup.CollectMembers(&sgHeadReceiver{
 		ctx:         ctx,
@@ -178,16 +161,10 @@ func putSG(cmd *cobra.Command, _ []string) {
 		c:           cli,
 		bearerToken: bearerToken,
 	}, cid, members)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	sgContent, err := sg.Marshal()
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	obj := objectSDK.NewRaw()
 	obj.SetContainerID(cid)
@@ -203,10 +180,7 @@ func putSG(cmd *cobra.Command, _ []string) {
 			client.WithBearer(bearerToken),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't put storage group: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't put storage group: %w", err))
 
 	cmd.Println("Storage group successfully stored")
 	cmd.Printf("  ID: %s\n  CID: %s\n", oid, cid)
@@ -221,28 +195,16 @@ func getSGID() (*objectSDK.ID, error) {
 
 func getSG(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	cid, err := getCID(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	id, err := getSGID()
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	bearerToken, err := sgBearerToken(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	addr := objectSDK.NewAddress()
 	addr.SetContainerID(cid)
@@ -251,10 +213,7 @@ func getSG(cmd *cobra.Command, _ []string) {
 	ctx := context.Background()
 
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	obj, err := cli.GetObject(ctx,
 		new(client.GetObjectParams).
@@ -264,16 +223,12 @@ func getSG(cmd *cobra.Command, _ []string) {
 			client.WithBearer(bearerToken),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't get storage group: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't get storage group: %w", err))
 
 	sg := storagegroupAPI.New()
-	if err := sg.Unmarshal(obj.Payload()); err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+
+	err = sg.Unmarshal(obj.Payload())
+	exitOnErr(cmd, err)
 
 	cmd.Printf("Expiration epoch: %d\n", sg.ExpirationEpoch())
 	cmd.Printf("Group size: %d\n", sg.ValidationDataSize())
@@ -290,30 +245,18 @@ func getSG(cmd *cobra.Command, _ []string) {
 
 func listSG(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	cid, err := getCID(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	bearerToken, err := sgBearerToken(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ids, err := cli.SearchObject(ctx,
 		new(client.SearchObjectParams).
@@ -324,10 +267,7 @@ func listSG(cmd *cobra.Command, _ []string) {
 			client.WithBearer(bearerToken),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't search storage groups: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't search storage groups: %w", err))
 
 	cmd.Printf("Found %d storage groups.\n", len(ids))
 
@@ -338,36 +278,21 @@ func listSG(cmd *cobra.Command, _ []string) {
 
 func delSG(cmd *cobra.Command, _ []string) {
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't fetch private key: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't fetch private key: %w", err))
 
 	cid, err := getCID(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	id, err := getSGID()
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	bearerToken, err := sgBearerToken(cmd)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	ctx := context.Background()
 
 	cli, tok, err := initSession(ctx, key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	addr := objectSDK.NewAddress()
 	addr.SetContainerID(cid)
@@ -381,10 +306,7 @@ func delSG(cmd *cobra.Command, _ []string) {
 			client.WithBearer(bearerToken),
 		)...,
 	)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't get storage group: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't get storage group: %w", err))
 
 	cmd.Println("Storage group removed successfully.")
 	cmd.Printf("  Tombstone: %s\n", tombstone.ObjectID())
diff --git a/cmd/neofs-cli/modules/util.go b/cmd/neofs-cli/modules/util.go
index f560aaa7c..146479024 100644
--- a/cmd/neofs-cli/modules/util.go
+++ b/cmd/neofs-cli/modules/util.go
@@ -118,10 +118,7 @@ var (
 			})
 
 			err := targetDB.Open()
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			defer targetDB.Close()
 
@@ -131,10 +128,7 @@ var (
 			}
 
 			err = locodedb.FillDatabase(locodeDB, airportDB, continentsDB, names, targetDB)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 		},
 	}
 )
@@ -157,18 +151,12 @@ var (
 			})
 
 			err := targetDB.Open()
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			defer targetDB.Close()
 
 			record, err := locodedb.LocodeRecord(targetDB, locodeInfoCode)
-			if err != nil {
-				cmd.PrintErrln(err)
-				return
-			}
+			exitOnErr(cmd, err)
 
 			cmd.Printf("Country: %s\n", record.CountryName())
 			cmd.Printf("Location: %s\n", record.LocationName())
@@ -255,28 +243,16 @@ func init() {
 
 func signBearerToken(cmd *cobra.Command, _ []string) {
 	btok, err := getBearerToken(cmd, "from")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	err = completeBearerToken(btok)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	err = btok.SignToken(key)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	to := cmd.Flag("to").Value.String()
 	jsonFlag, _ := cmd.Flags().GetBool("json")
@@ -284,16 +260,10 @@ func signBearerToken(cmd *cobra.Command, _ []string) {
 	var data []byte
 	if jsonFlag || len(to) == 0 {
 		data, err = btok.MarshalJSON()
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't JSON encode bearer token: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("can't JSON encode bearer token: %w", err))
 	} else {
 		data, err = btok.Marshal()
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't binary encode bearer token: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("can't binary encode bearer token: %w", err))
 	}
 
 	if len(to) == 0 {
@@ -303,44 +273,28 @@ func signBearerToken(cmd *cobra.Command, _ []string) {
 	}
 
 	err = os.WriteFile(to, data, 0644)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't write signed bearer token to file: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't write signed bearer token to file: %w", err))
 
 	cmd.Printf("signed bearer token was successfully dumped to %s\n", to)
 }
 
 func signSessionToken(cmd *cobra.Command, _ []string) {
 	path, err := cmd.Flags().GetString("from")
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	stok, err := getSessionToken(path)
 	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't read session token from %s: %w", path, err))
-		return
+		exitOnErr(cmd, fmt.Errorf("can't read session token from %s: %w", path, err))
 	}
 
 	key, err := getKey()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't get private key, make sure it is provided: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't get private key, make sure it is provided: %w", err))
 
 	err = stok.Sign(key)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't sign token: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't sign token: %w", err))
 
 	data, err := stok.MarshalJSON()
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't encode session token: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't encode session token: %w", err))
 
 	to := cmd.Flag("to").Value.String()
 	if len(to) == 0 {
@@ -350,8 +304,7 @@ func signSessionToken(cmd *cobra.Command, _ []string) {
 
 	err = os.WriteFile(to, data, 0644)
 	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't write signed session token to %s: %w", to, err))
-		return
+		exitOnErr(cmd, fmt.Errorf("can't write signed session token to %s: %w", to, err))
 	}
 
 	cmd.Printf("signed session token saved in %s\n", to)
@@ -363,24 +316,15 @@ func convertEACLTable(cmd *cobra.Command, _ []string) {
 	jsonFlag, _ := cmd.Flags().GetBool("json")
 
 	table, err := parseEACL(pathFrom)
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	var data []byte
 	if jsonFlag || len(to) == 0 {
 		data, err = table.MarshalJSON()
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't JSON encode extended ACL table: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("can't JSON encode extended ACL table: %w", err))
 	} else {
 		data, err = table.Marshal()
-		if err != nil {
-			cmd.PrintErrln(fmt.Errorf("can't binary encode extended ACL table: %w", err))
-			return
-		}
+		exitOnErr(cmd, errf("can't binary encode extended ACL table: %w", err))
 	}
 
 	if len(to) == 0 {
@@ -389,10 +333,7 @@ func convertEACLTable(cmd *cobra.Command, _ []string) {
 	}
 
 	err = os.WriteFile(to, data, 0644)
-	if err != nil {
-		cmd.PrintErrln(fmt.Errorf("can't write exteded ACL table to file: %w", err))
-		return
-	}
+	exitOnErr(cmd, errf("can't write exteded ACL table to file: %w", err))
 
 	cmd.Printf("extended ACL table was successfully dumped to %s\n", to)
 }
@@ -412,8 +353,7 @@ func processKeyer(cmd *cobra.Command, args []string) {
 		err = result.ParseMultiSig(args)
 	} else {
 		if len(args) > 1 {
-			cmd.PrintErrln(errKeyerSingleArgument)
-			return
+			exitOnErr(cmd, errKeyerSingleArgument)
 		}
 
 		var argument string
@@ -431,10 +371,7 @@ func processKeyer(cmd *cobra.Command, args []string) {
 		}
 	}
 
-	if err != nil {
-		cmd.PrintErrln(err)
-		return
-	}
+	exitOnErr(cmd, err)
 
 	result.PrettyPrint(uncompressed, useHex)
 }