diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# v3.1.0.1
+- Fix output when MPD does not report a next song.
+
 # v3.1
 - Reintroduce fix for multi-value tag arrays being in reverse order.
 
diff --git a/lib/MPD/Current/JSON/Builder.hs b/lib/MPD/Current/JSON/Builder.hs
--- a/lib/MPD/Current/JSON/Builder.hs
+++ b/lib/MPD/Current/JSON/Builder.hs
@@ -48,12 +48,14 @@
   , Current.length       = fromIntegral st.stPlaylistLength
   }
 
-mkFile :: MPD.Song -> MPD.Song -> Current.File
+mkFile :: MPD.Song -> Maybe MPD.Song -> Current.File
 mkFile cs ns = Current.File
   { Current.currentFile = if null $ MPD.toString cs.sgFilePath
                           then Nothing
                           else Just $ Current.MPDPath cs.sgFilePath
-  , Current.nextFile    = if null $ MPD.toString ns.sgFilePath
-                          then Nothing
-                          else Just $ Current.MPDPath ns.sgFilePath
+  , Current.nextFile    = do
+      nextSong <- ns
+      if null $ MPD.toString nextSong.sgFilePath
+        then Nothing
+        else Just $ Current.MPDPath nextSong.sgFilePath
   }
diff --git a/mpd-current-json.cabal b/mpd-current-json.cabal
--- a/mpd-current-json.cabal
+++ b/mpd-current-json.cabal
@@ -7,7 +7,7 @@
 -- PVP summary:     +-+------- breaking API changes
 --                  | | +----- non-breaking API additions
 --                  | | | +--- code changes with no API change
-version:            3.1.0.0
+version:            3.1.0.1
 synopsis:           Print current MPD song and status as JSON
 
 tested-with: GHC == { 9.12.2, 9.10.1, 9.6.7, 9.6.6, 9.4.8 }
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -23,6 +23,7 @@
       Config(..),
       Indent(Spaces) )
 import Data.ByteString.Lazy.Char8 qualified as C
+import Data.Maybe ( listToMaybe )
 import System.Exit ( die, exitSuccess )
 
 
@@ -35,23 +36,27 @@
   response <- withMpdOpts $ do
     cs <- MPD.currentSong
     st <- MPD.status
-    let nPos = st.stNextSongPos
-    ns <- MPD.playlistInfo nPos
+    ns <- case st.stNextSongPos of
+            Nothing -> pure []
+            nPos -> MPD.playlistInfo nPos
     pure (cs, st, ns)
 
   case response of
-    Right (Just cs, status, [ns]) ->
+    Right (Just cs, status, nextSongs) ->
       -- handle edge case where next song is the same as current
-      let opts' = if cs == ns
-                  then opts {optNext = NoNextSong}
-                  else opts
-      in printEncoded opts' cs ns status
+      let nextSong = case listToMaybe nextSongs of
+                       Just ns | cs == ns -> Nothing
+                       ns                 -> ns
+      in printEncoded opts cs nextSong status
 
     -- something tells me that exceptions are thrown before these get reached
     _ -> die "Couldn't get enough information from MPD."
 
-printEncoded :: Opts -> MPD.Song -> MPD.Song -> MPD.Status -> IO ()
-printEncoded opts cs ns status =
+printEncoded :: Opts -> MPD.Song -> Maybe MPD.Song -> MPD.Status -> IO ()
+printEncoded opts cs ns status
+  | opts.optNext == OnlyNextSong && ns == Nothing =
+      die "MPD did not report a next song."
+  | otherwise =
   let mpdState = mkState opts cs ns status
       finalJson = case opts.optNext of
                     OnlyNextSong -> object ["tags" .= mpdState.mpdNextTags]
@@ -94,7 +99,7 @@
  }
 
 -- | Main builder function that creates the complete state
-mkState :: Opts -> MPD.Song -> MPD.Song -> MPD.Status -> State
+mkState :: Opts -> MPD.Song -> Maybe MPD.Song -> MPD.Status -> State
 mkState opts currentSong nextSong status =
   State
   { mpdFile     = Builder.mkFile currentSong nextSong
@@ -103,8 +108,8 @@
   , mpdTags     = getTags currentSong
   , mpdNextTags = case opts.optNext of
       NoNextSong      -> Nothing
-      OnlyNextSong    -> Just (getTags nextSong)
-      IncludeNextSong -> Just (getTags nextSong)
+      OnlyNextSong    -> getTags <$> nextSong
+      IncludeNextSong -> getTags <$> nextSong
   }
 
 optsExecVersion :: Opts -> IO ()
