diff --git a/prettyprinter-graphviz.cabal b/prettyprinter-graphviz.cabal
--- a/prettyprinter-graphviz.cabal
+++ b/prettyprinter-graphviz.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                prettyprinter-graphviz
-version:             0.1.0.1
+version:             0.1.1.0
 synopsis:            a prettyprinter backend for graphviz
 description:         Contains utility functions for rendering pretty GraphViz labels.
 homepage:            https://github.com/georgefst/prettyprinter-graphviz
diff --git a/src/Data/Text/Prettyprint/Doc/Render/GraphViz.hs b/src/Data/Text/Prettyprint/Doc/Render/GraphViz.hs
--- a/src/Data/Text/Prettyprint/Doc/Render/GraphViz.hs
+++ b/src/Data/Text/Prettyprint/Doc/Render/GraphViz.hs
@@ -5,18 +5,20 @@
 
     -- * Error handling
     GraphVizRenderError(..),
+    renderSafe,
+    renderSafe',
 ) where
 
 import qualified Data.Text.Lazy as TL
 import qualified Data.Text as T
 
 import Control.Exception (
-        Exception,
-        displayException,
-        throw,
+    Exception,
+    displayException,
+    throw,
     )
 import Data.GraphViz.Attributes.Complete (
-        Label (HtmlLabel),
+    Label (HtmlLabel),
     )
 import qualified Data.GraphViz.Attributes.HTML as H
 import Data.Text.Prettyprint.Doc (
@@ -28,20 +30,11 @@
 
 -- | Render a document as a GraphViz label, using 'defaultLayoutOptions'.
 render :: Doc H.Attribute -> Label
-render = HtmlLabel . H.Text . render' . layoutPretty defaultLayoutOptions
+render = throwLeft . renderSafe
 
 -- | Render a document stream as HTML text for GraphViz. This provides more fine-grained control than 'render'.
 render' :: SimpleDocStream H.Attribute -> H.Text
-render' =
-    let go cs = \case
-            SFail           -> throw GVDocStreamFail
-            SEmpty          -> []
-            SChar c ds      -> renderText cs (T.singleton c) : go cs ds
-            SText _ txt ds  -> renderText cs txt : go cs ds
-            SLine n ds      -> H.Newline [] : renderText cs (T.replicate n " ") : go cs ds
-            SAnnPush col ds -> go (col : cs) ds
-            SAnnPop ds      -> go (tailDef (throw GVEmptyStack) cs) ds
-    in  go []
+render' = throwLeft . renderSafe'
 
 
 -- | The functions in this module can throw errors, given a malformed document stream.
@@ -57,11 +50,42 @@
         GVEmptyStack    -> t ++ "attempted to pop empty attribute stack"
         where t = "Failed to render HTML for GraphViz: "
 
--- | Equal to the funciton of the same name from [safe](https://hackage.haskell.org/package/safe).
-tailDef :: [a] -> [a] -> [a]
-tailDef e = \case
-    []     -> e
-    _ : xs -> xs
+-- | A total version of 'render'.
+renderSafe :: Doc H.Attribute -> Either GraphVizRenderError Label
+renderSafe = fmap (HtmlLabel . H.Text) . renderSafe' . layoutPretty defaultLayoutOptions
+
+-- | A total version of 'render\''.
+-- This can be seen as a generalisation of any of the other functions exported by this module.
+renderSafe' :: SimpleDocStream H.Attribute -> Either GraphVizRenderError H.Text
+renderSafe' =
+    let go cs = \case
+            SFail           -> Left GVDocStreamFail
+            SEmpty          -> Right []
+            SChar c ds      -> renderText cs (T.singleton c) ?: go cs ds
+            SText _ txt ds  -> renderText cs txt ?: go cs ds
+            SLine n ds      -> H.Newline [] ?: renderText cs (T.replicate n " ") ?: go cs ds
+            SAnnPush col ds -> go (col : cs) ds
+            SAnnPop ds      -> flip go ds =<< maybeToEither GVEmptyStack (tailMay cs)
+        infixr 0 ?:
+        (?:) = fmap . (:)
+    in  go []
+
+
+{- Internal utilities -}
+
+-- | On encountering a 'Left', throw it as an exception.
+throwLeft :: Exception e => Either e a -> a
+throwLeft = either throw id
+
+-- | Equal to the function of the same name from [extra](https://hackage.haskell.org/package/extra).
+maybeToEither :: a -> Maybe b -> Either a b
+maybeToEither x = maybe (Left x) Right
+
+-- | Equal to the function of the same name from [safe](https://hackage.haskell.org/package/safe).
+tailMay :: [a] -> Maybe [a]
+tailMay = \case
+    []     -> Nothing
+    _ : xs -> Just xs
 
 -- | Helper for rendering an individual 'H.TextItem'.
 renderText :: H.Attributes -> T.Text -> H.TextItem
