diff --git a/x/lockup/types/msgs.go b/x/lockup/types/msgs.go
index 1fb8e83d510ec07835f45d52c3012a3c469ac8a4..b456cc01c7aa7c28bb9e2db1b4776aa7c3a51c7d 100644
--- a/x/lockup/types/msgs.go
+++ b/x/lockup/types/msgs.go
@@ -111,12 +111,12 @@ func (m MsgBeginUnlocking) ValidateBasic() error {
 		return fmt.Errorf("invalid lockup ID, got %v", m.ID)
 	}
 
-	// only allow unlocks with a single denom
-	if m.Coins.Len() != 1 {
+	// only allow unlocks with a single denom or empty
+	if m.Coins.Len() > 1 {
 		return fmt.Errorf("can only unlock one denom per lock ID, got %v", m.Coins)
 	}
 
-	if !m.Coins.IsAllPositive() {
+	if !m.Coins.Empty() && !m.Coins.IsAllPositive() {
 		return fmt.Errorf("cannot unlock a zero or negative amount")
 	}
 
diff --git a/x/lockup/types/msgs_test.go b/x/lockup/types/msgs_test.go
index 29a1fc807f7e5af64e7a46ccc4adbd200878efb8..6d0ab74ed0700bc4e13a25f68f0b8f290a052c68 100644
--- a/x/lockup/types/msgs_test.go
+++ b/x/lockup/types/msgs_test.go
@@ -167,12 +167,22 @@ func TestMsgBeginUnlocking(t *testing.T) {
 			},
 		},
 		{
-			name: "not positive coins amount",
+			name: "zero coins (same as nil)",
 			msg: types.MsgBeginUnlocking{
 				Owner: addr1,
 				ID:    1,
 				Coins: sdk.NewCoins(sdk.NewCoin("test1", sdk.NewInt(0))),
 			},
+			expectPass: true,
+		},
+		{
+			name: "nil coins (unlock by ID)",
+			msg: types.MsgBeginUnlocking{
+				Owner: addr1,
+				ID:    1,
+				Coins: sdk.NewCoins(),
+			},
+			expectPass: true,
 		},
 	}