diff --git a/gopro-plus.cabal b/gopro-plus.cabal
--- a/gopro-plus.cabal
+++ b/gopro-plus.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.33.0.
+-- This file has been generated from package.yaml by hpack version 0.34.4.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: e57dbf9536773374bac2998b86c4f2901d748a645a488573462dfd7125d964c9
+-- hash: a792185c3e5dd0c5412e961456957e6810fcbcd183932f7db7743034baa59650
 
 name:           gopro-plus
-version:        0.4.1.3
+version:        0.5.0.0
 synopsis:       GoPro Plus Client API.
 description:    Please see the README on GitHub at <https://github.com/dustin/gopro-plus#readme>
 category:       Web
@@ -38,7 +38,10 @@
       Paths_gopro_plus
   hs-source-dirs:
       src
-  default-extensions: OverloadedStrings RecordWildCards NamedFieldPuns
+  default-extensions:
+      OverloadedStrings
+      RecordWildCards
+      NamedFieldPuns
   ghc-options: -Wall
   build-depends:
       aeson
@@ -70,7 +73,10 @@
       Paths_gopro_plus
   hs-source-dirs:
       test
-  default-extensions: OverloadedStrings RecordWildCards NamedFieldPuns
+  default-extensions:
+      OverloadedStrings
+      RecordWildCards
+      NamedFieldPuns
   ghc-options: -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       HUnit
diff --git a/src/GoPro/Plus/Upload.hs b/src/GoPro/Plus/Upload.hs
--- a/src/GoPro/Plus/Upload.hs
+++ b/src/GoPro/Plus/Upload.hs
@@ -36,7 +36,6 @@
 import           Control.Lens
 import           Control.Monad                (void, when, zipWithM_)
 import           Control.Monad.Catch          (MonadMask (..))
-import           Control.Monad.Fail           (MonadFail (..))
 import           Control.Monad.IO.Class       (MonadIO (..))
 import           Control.Monad.State          (StateT (..), evalStateT, get, gets, lift, modify)
 import           Control.Retry                (RetryStatus (..), exponentialBackoff, limitRetries, recoverAll)
@@ -44,12 +43,13 @@
 import           Data.Aeson.Lens
 import qualified Data.ByteString.Lazy         as BL
 import           Data.Char                    (toUpper)
+import           Data.List.NonEmpty           (NonEmpty (..))
+import qualified Data.List.NonEmpty           as NE
 import           Data.Maybe                   (fromJust)
 import qualified Data.Text                    as T
 import           Data.Time.Clock.POSIX        (getCurrentTime)
 import qualified Data.Vector                  as V
 import           Network.Wreq                 (Options, header, params, putWith)
-import           Prelude                      hiding (fail)
 import           System.FilePath.Posix        (takeExtension, takeFileName)
 import           System.IO                    (IOMode (..), SeekMode (..), hSeek, withFile)
 import           System.Posix.Files           (fileSize, getFileStatus)
@@ -78,7 +78,7 @@
   goproAuth = lift goproAuth
 
 data Env m = Env {
-  fileList   :: [FilePath],
+  fileList   :: NonEmpty FilePath,
   mediumType :: MediumType,
   extension  :: T.Text,
   filename   :: String,
@@ -91,18 +91,16 @@
 listUploading = filter (\Medium{..} -> _medium_ready_to_view == ViewUploading) . fst <$> list 30 1
 
 -- | Run an Uploader monad to create a single medium and upload the content for it.
-runUpload :: (HasGoProAuth m, MonadFail m, MonadIO m)
-          => [FilePath]   -- ^ The list of files to include in the medium.
+runUpload :: (HasGoProAuth m, MonadIO m)
+          => NonEmpty FilePath   -- ^ The list of files to include in the medium.
           -> Uploader m a -- ^ The action to perform.
           -> m a          -- ^ The result of the inner action.
 runUpload fileList = resumeUpload fileList ""
 
 -- | Run an Uploader monad for which we already know the MediumID
 -- (i.e., we're resuming an upload we previously began).
-resumeUpload :: (HasGoProAuth m, MonadFail m, MonadIO m) => [FilePath] -> MediumID -> Uploader m a -> m a
-resumeUpload [] _ _ = fail "empty file list"
-resumeUpload fileList@(fp:_) mediumID a =
-  goproAuth >>= \AuthInfo{..} -> evalStateT a Env{..}
+resumeUpload :: (HasGoProAuth m, MonadIO m) => NonEmpty FilePath -> MediumID -> Uploader m a -> m a
+resumeUpload fileList@(fp :| _) mediumID a = evalStateT a Env{..}
   where
     extension = T.pack . fmap toUpper . drop 1 . takeExtension $ filename
     filename = takeFileName fp
@@ -194,7 +192,6 @@
              -> Int          -- ^ The size of the file being uploaded in this part.
              -> Uploader m Upload
 createUpload did part fsize = do
-  Env{..} <- get
   AuthInfo{..} <- goproAuth
   let u1 = J.Object (mempty & at "derivative_id" ?~ J.String did
                      & at "camera_position" ?~ J.String "default"
@@ -218,7 +215,6 @@
           -> Int           -- ^ Size of this part.
           -> Uploader m Upload
 getUpload upid did part fsize = do
-  Env{..} <- get
   AuthInfo{..} <- goproAuth
 
   let pages = ceiling ((fromIntegral fsize :: Double) / fromIntegral chunkSize) :: Int
@@ -264,7 +260,6 @@
                -> Integer      -- ^ The size of the file that was uploaded.
                -> Uploader m ()
 completeUpload upid did part fsize = do
-  Env{..} <- get
   AuthInfo{..} <- goproAuth
   let u2 = J.Object (mempty & at "id" ?~ J.String upid
                      & at "item_number" ?~ J.Number (fromIntegral part)
@@ -303,10 +298,9 @@
     popts tok = authOpts tok & header "Accept" .~  ["application/vnd.gopro.jk.user-uploads+json; version=2.0.0"]
 
 -- | Convenience action to upload a single medium.
-uploadMedium :: (HasGoProAuth m, MonadMask m, MonadFail m, MonadIO m)
-             => [FilePath] -- ^ Parts of a single medium to upload (e.g., a video file).
+uploadMedium :: (HasGoProAuth m, MonadMask m, MonadIO m)
+             => NonEmpty FilePath -- ^ Parts of a single medium to upload (e.g., a video file).
              -> m MediumID
-uploadMedium [] = fail "no files provided"
 uploadMedium fps = runUpload fps $ do
   mid <- createMedium
   did <- createSource (length fps)
@@ -315,7 +309,7 @@
             Upload{..} <- createUpload did n (fromInteger fsize)
             mapM_ (uploadChunk fp) _uploadParts
             completeUpload _uploadID did n fsize
-        ) fps [1..]
+        ) (NE.toList fps) [1..]
   markAvailable did
 
   pure mid
