diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Revision history for lsp-types
 
+## 2.0.1.1
+
+* Fix parsing of notifications with missing params
+
 ## 2.0.1.0
 
 * Removed deprecation pragmas from fields, as these cannot currently be avoided.
diff --git a/lsp-types.cabal b/lsp-types.cabal
--- a/lsp-types.cabal
+++ b/lsp-types.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               lsp-types
-version:            2.0.1.0
+version:            2.0.1.1
 synopsis:
   Haskell library for the Microsoft Language Server Protocol, data types
 
diff --git a/src/Language/LSP/Protocol/Message/Types.hs b/src/Language/LSP/Protocol/Message/Types.hs
--- a/src/Language/LSP/Protocol/Message/Types.hs
+++ b/src/Language/LSP/Protocol/Message/Types.hs
@@ -108,8 +108,19 @@
 deriving stock instance Eq   (MessageParams m) => Eq (TNotificationMessage m)
 deriving stock instance Show (MessageParams m) => Show (TNotificationMessage m)
 
+{- Note [Missing 'params']
+The 'params' field on requrests and notificaoins may be omitted according to the
+JSON-RPC spec, but that doesn't quite work the way we want with the generic aeson
+instance. Even if the 'MessageParams' type family happens to resolve to a 'Maybe',
+we handle it generically and so we end up asserting that it must be present.
+
+We fix this in a slightly dumb way by just adding the field in if it is missing,
+set to null (which parses correctly for those 'Maybe' parameters also).
+-}
+
 instance (FromJSON (MessageParams m), FromJSON (SMethod m)) => FromJSON (TNotificationMessage m) where
-  parseJSON = genericParseJSON lspOptions
+  -- See Note [Missing 'params']
+  parseJSON = genericParseJSON lspOptions . addNullField "params"
 instance (ToJSON (MessageParams m)) => ToJSON (TNotificationMessage m) where
   toJSON     = genericToJSON lspOptions
   toEncoding = genericToEncoding lspOptions
@@ -126,6 +137,7 @@
 deriving stock instance Show (MessageParams m) => Show (TRequestMessage m)
 
 instance (FromJSON (MessageParams m), FromJSON (SMethod m)) => FromJSON (TRequestMessage m) where
+  -- See Note [Missing 'params']
   parseJSON = genericParseJSON lspOptions . addNullField "params"
 instance (ToJSON (MessageParams m)) => ToJSON (TRequestMessage m) where
   toJSON     = genericToJSON lspOptions
diff --git a/test/JsonSpec.hs b/test/JsonSpec.hs
--- a/test/JsonSpec.hs
+++ b/test/JsonSpec.hs
@@ -41,7 +41,9 @@
 spec :: Spec
 spec = do
   describe "dispatcher" jsonSpec
-  describe "ResponseMessage"  responseMessageSpec
+  describe "RequestMessage" requestMessageSpec
+  describe "ResponseMessage" responseMessageSpec
+  describe "NotificationMesssage" notificationMessageSpec
 
 -- ---------------------------------------------------------------------
 
@@ -61,6 +63,13 @@
         `shouldNotBe` Nothing
 
 
+requestMessageSpec :: Spec
+requestMessageSpec = do
+  describe "edge cases" $ do
+    it "handles missing params field" $ do
+      J.eitherDecode "{ \"jsonrpc\": \"2.0\", \"id\": 15, \"method\": \"shutdown\"}"
+        `shouldBe` Right (TRequestMessage "2.0" (IdInt 15) SMethod_Shutdown Nothing)
+
 responseMessageSpec :: Spec
 responseMessageSpec = do
   describe "edge cases" $ do
@@ -68,9 +77,6 @@
       let input = "{\"jsonrpc\": \"2.0\", \"id\": 123, \"result\": null}"
         in  J.decode input `shouldBe` Just
               ((TResponseMessage "2.0" (Just (IdInt 123)) (Right $ InL J.Null)) :: TResponseMessage 'Method_WorkspaceExecuteCommand)
-    it "handles missing params field" $ do
-      J.eitherDecode "{ \"jsonrpc\": \"2.0\", \"id\": 15, \"method\": \"shutdown\"}"
-        `shouldBe` Right (TRequestMessage "2.0" (IdInt 15) SMethod_Shutdown Nothing)
   describe "invalid JSON" $ do
     it "throws if neither result nor error is present" $ do
       (J.eitherDecode "{\"jsonrpc\":\"2.0\",\"id\":1}" :: Either String (TResponseMessage 'Method_Initialize))
@@ -81,6 +87,13 @@
         :: Either String (TResponseMessage 'Method_Initialize))
         `shouldSatisfy`
           (either (\err -> "Error in $: both error and result cannot be present" `isPrefixOf` err) (\_ -> False))
+
+notificationMessageSpec :: Spec
+notificationMessageSpec = do
+  describe "edge cases" $ do
+    it "handles missing params field" $ do
+      J.eitherDecode "{ \"jsonrpc\": \"2.0\", \"method\": \"exit\"}"
+        `shouldBe` Right (TNotificationMessage "2.0" SMethod_Exit Nothing)
 
 -- ---------------------------------------------------------------------
 
