diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,4 +1,18 @@
 
+0.3
+---
+
+API changes:
+ * Added 'aspellDictionaries' to obtain the list of installed
+   dictionaries.
+
+Other changes:
+ * startAspell now gracefully handles Aspell startup failures by
+   reporting Aspell's standard error output in the event of a failed
+   startup. It also sanity-checks the Aspell pipe mode identification
+   string. (Fixes #2, #3.)
+
+
 0.2
 ---
 
diff --git a/aspell-pipe.cabal b/aspell-pipe.cabal
--- a/aspell-pipe.cabal
+++ b/aspell-pipe.cabal
@@ -1,5 +1,5 @@
 name:                aspell-pipe
-version:             0.2
+version:             0.3
 synopsis:            Pipe-based interface to the Aspell program
 description:         A pipe-based interface to the Aspell program (no
                      dynamic linking required).
@@ -26,5 +26,5 @@
   hs-source-dirs:      src
   default-language:    Haskell2010
   build-depends:       base >=4.8 && <5,
-                       process >= 1.6,
+                       process >= 1.3,
                        text
diff --git a/src/Text/Aspell.hs b/src/Text/Aspell.hs
--- a/src/Text/Aspell.hs
+++ b/src/Text/Aspell.hs
@@ -18,11 +18,14 @@
   , stopAspell
   , askAspell
   , aspellIdentification
+  , aspellDictionaries
   )
 where
 
 import qualified Control.Exception as E
-import Control.Monad (forM)
+import Control.Monad (forM, when, void)
+import Control.Concurrent (forkIO, killThread)
+import Control.Concurrent.MVar (takeMVar, newEmptyMVar, putMVar)
 import Data.Monoid ((<>))
 import Data.Maybe (fromJust)
 import Text.Read (readMaybe)
@@ -79,31 +82,101 @@
 -- message on failure or an Aspell handle on success.
 startAspell :: [AspellOption] -> IO (Either String Aspell)
 startAspell options = do
-    let proc = (P.proc "aspell" ("-a" : (concat $ optionToArgs <$> options)))
-               { P.std_in = P.CreatePipe
-               , P.std_out = P.CreatePipe
-               , P.std_err = P.NoStream
-               }
+    optResult <- checkOptions options
+    case optResult of
+        Just e -> return $ Left e
+        Nothing -> tryConvert $ do
+            let proc = (P.proc aspellCommand ("-a" : (concat $ optionToArgs <$> options)))
+                       { P.std_in = P.CreatePipe
+                       , P.std_out = P.CreatePipe
+                       , P.std_err = P.CreatePipe
+                       }
 
-    result <- E.try $ P.createProcess proc
-    case result of
-        Left (e::E.SomeException) -> return $ Left $ show e
-        Right (Just inH, Just outH, Nothing, ph) -> do
-            identResult <- E.try $ T.hGetLine outH
-            case identResult of
-                Left (e::E.SomeException) -> return $ Left $ show e
+            (Just inH, Just outH, Just errH, ph) <- P.createProcess proc
+
+            -- Set up an mvar to hold the first available aspell output.
+            -- In this we store the first available stdout or stderr
+            -- line; if aspell dies immediately then we can expect a
+            -- stderr read (the error message), but on success we expect
+            -- a stdout read (the identification string). We fork two
+            -- threads: one to read stdout, one stderr. Whichever one
+            -- gets a result first tells us whether Aspell started
+            -- successfully. If the stderr thread wins, the stdout
+            -- thread will get an exception on hGetLine due to stdout
+            -- being closed, so we have to handle that. If the stdout
+            -- thread wins, the stderr thread will block forever and we
+            -- need to kill it.
+            initialResult <- newEmptyMVar
+
+            void $ forkIO $ do
+                identResult <- E.try $ T.hGetLine outH
+                case identResult of
+                    -- A failure means aspell died, so the stderr thread
+                    -- should have something to read.
+                    Left (_::E.SomeException) -> return ()
+                    Right ident -> putMVar initialResult $ Right ident
+
+            errThread <- forkIO $ do
+                err <- T.hGetLine errH
+                putMVar initialResult $ Left err
+
+            status <- takeMVar initialResult
+            case status of
+                Left e -> error $ "Error starting aspell: " <> show e
                 Right ident -> do
-                    let as = Aspell { aspellProcessHandle  = ph
-                                    , aspellStdin          = inH
-                                    , aspellStdout         = outH
-                                    , aspellIdentification = ident
-                                    }
+                    killThread errThread
 
-                    -- Enable terse mode with aspell to improve performance.
-                    T.hPutStrLn inH "!"
+                    -- Now that aspell has started and we got an
+                    -- identification string, we need to make sure it
+                    -- looks legitimate before we proceed.
+                    case validIdent ident of
+                        False -> error $ "Unexpected identification string: " <> show ident
+                        True -> do
+                            let as = Aspell { aspellProcessHandle  = ph
+                                            , aspellStdin          = inH
+                                            , aspellStdout         = outH
+                                            , aspellIdentification = ident
+                                            }
 
-                    return $ Right as
+                            -- Enable terse mode with aspell to improve performance.
+                            T.hPutStrLn inH "!"
 
+                            return as
+
+validIdent :: T.Text -> Bool
+validIdent s =
+    "@(#) International Ispell Version" `T.isPrefixOf` s &&
+    "but really Aspell" `T.isInfixOf` s
+
+checkOptions :: [AspellOption] -> IO (Maybe String)
+checkOptions [] = return Nothing
+checkOptions (o:os) = do
+    result <- checkOption o
+    case result of
+        Nothing -> checkOptions os
+        Just msg -> return $ Just msg
+
+aspellCommand :: String
+aspellCommand = "aspell"
+
+checkOption :: AspellOption -> IO (Maybe String)
+checkOption (UseDictionary d) = do
+    -- Get the list of installed dictionaries and check whether the
+    -- desired dictionary is included.
+    dictListResult <- aspellDictionaries
+    case dictListResult of
+        Left msg -> return $ Just msg
+        Right dictList ->
+            case d `elem` dictList of
+                True -> return Nothing
+                False -> return $ Just $ "Requested dictionary " <> show d <> " is not installed"
+
+-- | Obtain the list of installed Aspell dictionaries.
+aspellDictionaries :: IO (Either String [T.Text])
+aspellDictionaries =
+    tryConvert $
+    (T.pack <$>) <$> lines <$> P.readProcess aspellCommand ["dicts"] ""
+
 optionToArgs :: AspellOption -> [String]
 optionToArgs (UseDictionary d) = ["-d", T.unpack d]
 
@@ -170,3 +243,11 @@
         False -> do
             rest <- readLinesUntil h f
             return $ line : rest
+
+tryConvert :: IO a -> IO (Either String a)
+tryConvert act = do
+    result <- E.try act
+    return $ either (Left . showException) Right result
+
+showException :: E.SomeException -> String
+showException = show
