diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,14 +1,16 @@
 gtk-sni-tray
-===============
+============
+![Build Status](https://github.com/taffybar/gtk-sni-tray/actions/workflows/build.yml/badge.svg)
+[![Hackage](https://img.shields.io/hackage/v/gtk-sni-tray.svg?logo=haskell&label=gtk-sni-tray)](https://hackage.haskell.org/package/gtk-sni-tray) [![Stackage LTS](http://stackage.org/package/gtk-sni-tray/badge/lts)](http://stackage.org/lts/package/gtk-sni-tray) [![Stackage Nightly](http://stackage.org/package/gtk-sni-tray/badge/nightly)](http://stackage.org/nightly/package/gtk-sni-tray)
 
-gtk-sni-tray provides a [StatusNotifierHost](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierHost/) widget written using the gtk+3 bindings for haskell provided by [gi-gtk](https://hackage.haskell.org/package/gi-gtk). It also provides a simple standalone executable, `gtk-sni-tray-standalone`, that is configured with command line arguments. This executable will run the aforementioned widget by itself in a strut window, on each monitor for each it is requested.
+gtk-sni-tray provides a [StatusNotifierHost](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierHost/) widget written using the gtk+3 bindings for haskell provided by [gi-gtk](https://hackage.haskell.org/package/gi-gtk). It also provides a simple standalone executable, `gtk-sni-tray-standalone`, that is configured with command line arguments. This executable will run the aforementioned widget by itself in a strut window, on each monitor it is requested.
 
 taffybar
-----------
-It is generally recommeneded that you use this widget through [taffybar](https://github.com/travitch/taffybar) with [this module](https://github.com/travitch/taffybar/blob/master/src/System/Taffybar/Widget/SNITray.hs), which will allow you to combine it with other useful widgets, and will give more flexibility in configuration.
+--------
+It is generally recommeneded that you use this widget through [taffybar](https://github.com/travitch/taffybar) with [this module](https://github.com/travitch/taffybar/blob/master/src/System/Taffybar/Widget/SNITray.hs), which will allow you to combine it with other useful widgets, and will allow more flexibility in configuration.
 
 StatusNotifierWatcher
---------------------------
+---------------------
 By default, it is assumed that you are running an isolated StatusNotifierWatcher daemon. [status-notifier-item](https://github.com/IvanMalison/status-notifier-item) provides a StatusNotifierWatcher executable that you can use for this purpose. If you get an error like
 
 ```
@@ -18,7 +20,10 @@
 when you start `gtk-sni-tray-standalone` it is probably because you have not started a StatusNotifierWatcher on your system. You can solve this problem by passing the `--watcher` flag to `gtk-sni-tray-standalone`, but this is not recommeneded, because many SNI processes do not monitor for new watcher processes, and so may not immediately register when this new watcher is started.
 
 Installation
----------------
+------------
 
-Both [`stack`](https://www.haskell.org/cabal/download.html) and [`cabal`](https://www.haskell.org/cabal/download.html) can be used to install gtk-sni-tray.
+[`nix`](https://nixos.org/download.html),
+[`stack`](https://docs.haskellstack.org/en/stable/README/) and
+[`cabal`](https://www.haskell.org/cabal/download.html) can all be used to
+install gtk-sni-tray.
 
diff --git a/gtk-sni-tray.cabal b/gtk-sni-tray.cabal
--- a/gtk-sni-tray.cabal
+++ b/gtk-sni-tray.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.34.7.
 --
 -- see: https://github.com/sol/hpack
 
 name:           gtk-sni-tray
-version:        0.1.8.0
+version:        0.1.8.1
 synopsis:       A standalone StatusNotifierItem/AppIndicator tray
 description:    Please see the README on Github at <https://github.com/IvanMalison/gtk-sni-tray#readme>
 category:       System
@@ -47,10 +47,10 @@
     , gi-cairo-connector
     , gi-cairo-render
     , gi-dbusmenugtk3
-    , gi-gdk
+    , gi-gdk >=3.0.25 && <4
     , gi-gdkpixbuf >=2.0.16
     , gi-glib
-    , gi-gtk >=3.0.21
+    , gi-gtk >=3.0.38 && <4
     , gtk-strut >=0.1.2.1
     , haskell-gi >=0.21.2
     , haskell-gi-base >=0.21.1
diff --git a/src/StatusNotifier/Tray.hs b/src/StatusNotifier/Tray.hs
--- a/src/StatusNotifier/Tray.hs
+++ b/src/StatusNotifier/Tray.hs
@@ -4,15 +4,18 @@
 module StatusNotifier.Tray where
 
 import           Control.Concurrent.MVar as MV
+import           Control.Exception.Base
 import           Control.Exception.Enclosed (catchAny)
 import           Control.Monad
 import           Control.Monad.Trans.Class
 import           Control.Monad.Trans.Maybe
 import           DBus.Client
 import qualified DBus.Internal.Types as DBusTypes
+import           Data.Bool (bool)
 import qualified Data.ByteString as BS
 import           Data.Coerce
 import           Data.Foldable (traverse_)
+import           Data.GI.Base.GError
 import           Data.Int
 import           Data.List
 import qualified Data.Map.Strict as Map
@@ -28,7 +31,7 @@
 import           GI.Gdk.Objects.Screen
 import           GI.Gdk.Structs.EventScroll
 import           GI.GdkPixbuf.Enums
-import           GI.GdkPixbuf.Objects.Pixbuf
+import           GI.GdkPixbuf.Objects.Pixbuf as Gdk
 import qualified GI.Gtk as Gtk
 import           GI.Gtk.Flags
 import           GI.Gtk.Objects.IconTheme
@@ -70,7 +73,8 @@
       targetWidth = case orientation of
                       Gtk.OrientationHorizontal -> False
                       _ -> True
-      (scaledWidth, scaledHeight) = getScaledWidthHeight targetWidth size width height
+      (scaledWidth, scaledHeight) =
+        getScaledWidthHeight targetWidth size width height
   trayLogger DEBUG $
              printf
              "Scaling pb to %s, actualW: %s, actualH: %s, scaledW: %s, scaledH: %s"
@@ -100,6 +104,26 @@
 
   return themeForIcon
 
+catchGErrorsAsLeft :: IO a -> IO (Either GError a)
+catchGErrorsAsLeft action = catch (Right <$> action) (return . Left)
+
+catchGErrorsAsNothing :: IO a -> IO (Maybe a)
+catchGErrorsAsNothing action = catchGErrorsAsLeft action >>= rightToJustLogLeft
+       where rightToJustLogLeft (Right value) = return $ Just value
+             rightToJustLogLeft (Left error) = do
+               trayLogger WARNING $ printf "Encountered error: %s" $ show error
+               return Nothing
+
+safePixbufNewFromFile :: FilePath -> IO (Maybe Gdk.Pixbuf)
+safePixbufNewFromFile =
+  handleResult . catchGErrorsAsNothing . Gdk.pixbufNewFromFile
+  where
+#if MIN_VERSION_gi_gdkpixbuf(2,0,26)
+    handleResult = fmap join
+#else
+    handleResult = id
+#endif
+
 getIconPixbufByName :: Int32 -> T.Text -> Maybe String -> IO (Maybe Pixbuf)
 getIconPixbufByName size name themePath = do
   trayLogger DEBUG $ printf "Getting Pixbuf from name for %s" name
@@ -132,7 +156,7 @@
 #else
     let handleResult = sequenceA
 #endif
-    handleResult $ pixbufNewFromFile <$> maybeFile
+    handleResult $ safePixbufNewFromFile <$> maybeFile
 
 getIconPathFromThemePath :: String -> String -> IO (Maybe String)
 getIconPathFromThemePath name themePath = if name == "" then return Nothing else do
@@ -297,7 +321,8 @@
 
                         when requestResize $ do
                           trayLogger DEBUG "Requesting resize"
-                          pixBuf <- getInfo info serviceName >>= getScaledPixBufFromInfo size
+                          pixBuf <- getInfo info serviceName >>=
+                                    getScaledPixBufFromInfo size
                           when (isNothing pixBuf) $
                                trayLogger WARNING $
                                           printf "Got null pixbuf for info %s" $
@@ -341,12 +366,11 @@
             button <- Gdk.getEventButtonButton event
             x <- round <$> Gdk.getEventButtonXRoot event
             y <- round <$> Gdk.getEventButtonYRoot event
-            isMenu <- getInfoAttr itemIsMenu False serviceName
-            let action = if isMenu then PopupMenu else
-                  case button of
-                    1 -> leftClickAction
-                    2 -> middleClickAction
-                    3 -> rightClickAction
+            action <- case button of
+              1 -> bool leftClickAction PopupMenu <$> getInfoAttr
+                   itemIsMenu True serviceName
+              2 -> return middleClickAction
+              _ -> return rightClickAction
             case action of
               Activate -> void $ IC.activate client serviceName servicePath x y
               SecondaryActivate -> void $ IC.secondaryActivate client
@@ -385,7 +409,7 @@
       updateHandler ItemRemoved ItemInfo { itemServiceName = name }
         = getContext name >>= removeWidget
         where removeWidget Nothing =
-                trayLogger INFO "Attempt to remove widget with unrecognized service name."
+                trayLogger WARNING "removeWidget: unrecognized service name."
               removeWidget (Just ItemContext { contextButton = widgetToRemove }) =
                 do
                   Gtk.containerRemove trayBox widgetToRemove
@@ -395,7 +419,8 @@
       updateHandler OverlayIconUpdated i = updateIconFromInfo i
 
       updateHandler ToolTipUpdated info@ItemInfo { itemServiceName = name } =
-        void $ getContext name >>= traverse (flip setTooltipText info . contextButton)
+        void $ getContext name >>=
+             traverse (flip setTooltipText info . contextButton)
 
       updateHandler _ _ = return ()
 
