diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## Stache 1.1.0
+
+* Added `mustacheRenderW` that allows to render a `Template` collecting
+  warnings in the process. Also added the `MusthacheWarning` type
+  representing the warnings themselves and `displayMustacheWarning` to
+  pretty-print the warnings.
+
 ## Stache 1.0.0
 
 * Improved metadata and documentation.
diff --git a/Text/Mustache/Render.hs b/Text/Mustache/Render.hs
--- a/Text/Mustache/Render.hs
+++ b/Text/Mustache/Render.hs
@@ -15,29 +15,29 @@
 {-# LANGUAGE OverloadedStrings #-}
 
 module Text.Mustache.Render
-  ( renderMustache )
+  ( renderMustache
+  , renderMustacheW )
 where
 
 import Control.Monad.Reader
-import Control.Monad.Writer.Strict
+import Control.Monad.State.Strict (State, modify', execState)
 import Data.Aeson
 import Data.Foldable (asum)
 import Data.List (tails)
 import Data.List.NonEmpty (NonEmpty (..))
-import Data.Maybe (fromMaybe)
+import Data.Semigroup ((<>))
 import Data.Text (Text)
 import Text.Megaparsec.Pos (Pos, unPos)
 import Text.Mustache.Type
-import qualified Data.ByteString.Lazy   as B
-import qualified Data.HashMap.Strict    as H
-import qualified Data.List.NonEmpty     as NE
-import qualified Data.Map               as M
-import qualified Data.Semigroup         as S
-import qualified Data.Text              as T
-import qualified Data.Text.Encoding     as T
-import qualified Data.Text.Lazy         as TL
-import qualified Data.Text.Lazy.Builder as B
-import qualified Data.Vector            as V
+import qualified Data.HashMap.Strict     as H
+import qualified Data.List.NonEmpty      as NE
+import qualified Data.Map                as M
+import qualified Data.Semigroup          as S
+import qualified Data.Text               as T
+import qualified Data.Text.Lazy          as TL
+import qualified Data.Text.Lazy.Builder  as B
+import qualified Data.Text.Lazy.Encoding as TL
+import qualified Data.Vector             as V
 
 #if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
@@ -50,8 +50,10 @@
 -- and accumulate the result as 'B.Builder' data which is then turned into a
 -- lazy 'TL.Text'.
 
-type Render a = ReaderT RenderContext (Writer B.Builder) a
+type Render a = ReaderT RenderContext (State S) a
 
+data S = S ([MustacheWarning] -> [MustacheWarning]) B.Builder
+
 -- | The render monad context.
 
 data RenderContext = RenderContext
@@ -69,7 +71,14 @@
 -- for interpolation.
 
 renderMustache :: Template -> Value -> TL.Text
-renderMustache t =
+renderMustache t = snd . renderMustacheW t
+
+-- | Like 'renderMustache', but also returns a collection of warnings.
+--
+-- @since 1.1.0
+
+renderMustacheW :: Template -> Value -> ([MustacheWarning], TL.Text)
+renderMustacheW t =
   runRender (renderPartial (templateActual t) Nothing renderNode) t
 
 -- | Render a single 'Node'.
@@ -77,9 +86,9 @@
 renderNode :: Node -> Render ()
 renderNode (TextBlock txt) = outputIndented txt
 renderNode (EscapedVar k) =
-  lookupKey k >>= outputRaw . escapeHtml . renderValue
+  lookupKey k >>= renderValue k >>= outputRaw . escapeHtml
 renderNode (UnescapedVar k) =
-  lookupKey k >>= outputRaw . renderValue
+  lookupKey k >>= renderValue k >>= outputRaw
 renderNode (Section k ns) = do
   val <- lookupKey k
   enterSection k $
@@ -103,9 +112,10 @@
 -- | Run 'Render' monad given template to render and a 'Value' to take
 -- values from.
 
-runRender :: Render a -> Template -> Value -> TL.Text
-runRender m t v = (B.toLazyText . execWriter) (runReaderT m rc)
+runRender :: Render a -> Template -> Value -> ([MustacheWarning], TL.Text)
+runRender m t v = (ws [], B.toLazyText b)
   where
+    S ws b = execState (runReaderT m rc) (S id mempty)
     rc = RenderContext
       { rcIndent   = Nothing
       , rcContext  = v :| []
@@ -117,7 +127,7 @@
 -- | Output a piece of strict 'Text'.
 
 outputRaw :: Text -> Render ()
-outputRaw = tell . B.fromText
+outputRaw = tellBuilder . B.fromText
 {-# INLINE outputRaw #-}
 
 -- | Output indentation consisting of appropriate number of spaces.
@@ -185,7 +195,11 @@
   v <- asks rcContext
   p <- asks rcPrefix
   let f x = asum (simpleLookup False (x <> k) <$> v)
-  (return . fromMaybe Null . asum) (fmap (f . Key) . reverse . tails $ unKey p)
+  case asum (fmap (f . Key) . reverse . tails $ unKey p) of
+    Nothing ->
+      Null <$ tellWarning (MustacheVariableNotFound (p <> k))
+    Just r ->
+      return r
 
 -- | Lookup a 'Value' by traversing another 'Value' using given 'Key' as
 -- “path”.
@@ -225,6 +239,16 @@
 ----------------------------------------------------------------------------
 -- Helpers
 
+-- | Register a warning.
+
+tellWarning :: MustacheWarning -> Render ()
+tellWarning w = modify' $ \(S ws b) -> S (ws . (w:)) b
+
+-- | Register a piece of output.
+
+tellBuilder :: B.Builder -> Render ()
+tellBuilder b' = modify' $ \(S ws b) -> S ws (b <> b')
+
 -- | Add two @'Maybe' 'Pos'@ values together.
 
 addIndents :: Maybe Pos -> Maybe Pos -> Maybe Pos
@@ -254,10 +278,20 @@
 
 -- | Render Aeson's 'Value' /without/ HTML escaping.
 
-renderValue :: Value -> Text
-renderValue Null         = ""
-renderValue (String str) = str
-renderValue value        = (T.decodeUtf8 . B.toStrict . encode) value
+renderValue :: Key -> Value -> Render Text
+renderValue k v =
+  case v of
+    Null       -> return ""
+    String str -> return str
+    Object _ -> do
+      tellWarning (MustacheDirectlyRenderedValue k)
+      render v
+    Array _ -> do
+      tellWarning (MustacheDirectlyRenderedValue k)
+      render v
+    _ -> render v
+  where
+    render = return . TL.toStrict . TL.decodeUtf8 . encode
 {-# INLINE renderValue #-}
 
 -- | Escape HTML represented as strict 'Text'.
diff --git a/Text/Mustache/Type.hs b/Text/Mustache/Type.hs
--- a/Text/Mustache/Type.hs
+++ b/Text/Mustache/Type.hs
@@ -23,7 +23,9 @@
   , Key (..)
   , showKey
   , PName (..)
-  , MustacheException (..) )
+  , MustacheException (..)
+  , MustacheWarning (..)
+  , displayMustacheWarning )
 where
 
 import Control.DeepSeq
@@ -123,3 +125,26 @@
 #else
 instance Exception MustacheException
 #endif
+
+-- | Warning that may be generated during rendering of a 'Template'.
+--
+-- @since 1.1.0
+
+data MustacheWarning
+  = MustacheVariableNotFound Key
+    -- ^ The template contained a variable for which there was no data
+    -- counterpart in the current context.
+  | MustacheDirectlyRenderedValue Key
+    -- ^ A complex value such as an 'Object' or 'Array' was directly
+    -- rendered into the template.
+  deriving (Eq, Show, Typeable, Generic)
+
+-- | Pretty-print a 'MustacheWarning'.
+--
+-- @since 1.1.0
+
+displayMustacheWarning :: MustacheWarning -> String
+displayMustacheWarning (MustacheVariableNotFound key) =
+  "Referenced value was not provided, key: " ++ T.unpack (showKey key)
+displayMustacheWarning (MustacheDirectlyRenderedValue key) =
+  "Complex value rendered as such, key: " ++ T.unpack (showKey key)
diff --git a/stache.cabal b/stache.cabal
--- a/stache.cabal
+++ b/stache.cabal
@@ -1,5 +1,5 @@
 name:                 stache
-version:              1.0.0
+version:              1.1.0
 cabal-version:        >= 1.18
 tested-with:          GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.1
 license:              BSD3
diff --git a/tests/Text/Mustache/RenderSpec.hs b/tests/Text/Mustache/RenderSpec.hs
--- a/tests/Text/Mustache/RenderSpec.hs
+++ b/tests/Text/Mustache/RenderSpec.hs
@@ -23,8 +23,11 @@
 
 spec :: Spec
 spec = describe "renderMustache" $ do
-  let r ns value =
+  let w ns value =
         let template = Template "test" (M.singleton "test" ns)
+        in fst (renderMustacheW template value)
+      r ns value =
+        let template = Template "test" (M.singleton "test" ns)
         in renderMustache template value
       key = Key . pure
   it "leaves text block “as is”" $
@@ -37,11 +40,22 @@
     r [UnescapedVar (key "foo")]
       (object ["foo" .= ("<html>&\"something\"</html>" :: Text)])
       `shouldBe` "<html>&\"something\"</html>"
+  context "when rendering a variable" $ do
+    context "when variable does not exist" $
+      it "generates correct warning" $
+        w [EscapedVar (key "foo")] (object []) `shouldBe`
+          [MustacheVariableNotFound (key "foo")]
+    context "when variable is not non-scalar" $
+      it "generates correct warning" $
+        w [EscapedVar (key "foo")] (object ["foo" .= object []]) `shouldBe`
+          [MustacheDirectlyRenderedValue (key "foo")]
   context "when rendering a section" $ do
     let nodes = [Section (key "foo") [UnescapedVar (key "bar"), TextBlock "*"]]
-    context "when the key is not present" $
+    context "when the key is not present" $ do
       it "renders nothing" $
         r nodes (object []) `shouldBe` ""
+      it "generates correct warning" $
+        w nodes (object []) `shouldBe` [MustacheVariableNotFound (key "foo")]
     context "when the key is present" $ do
       context "when the key is a “false” value" $ do
         it "skips the Null value" $
@@ -96,9 +110,11 @@
             `shouldBe` "x"
   context "when rendering an inverted section" $ do
     let nodes = [InvertedSection (key "foo") [TextBlock "Here!"]]
-    context "when the key is not present" $
+    context "when the key is not present" $ do
       it "renders the inverse section" $
         r nodes (object []) `shouldBe` "Here!"
+      it "generates correct warning" $
+        w nodes (object []) `shouldBe` [MustacheVariableNotFound (key "foo")]
     context "when the key is present" $ do
       context "when the key is a “false” value" $ do
         it "renders with Null value" $
diff --git a/tests/Text/Mustache/TypeSpec.hs b/tests/Text/Mustache/TypeSpec.hs
--- a/tests/Text/Mustache/TypeSpec.hs
+++ b/tests/Text/Mustache/TypeSpec.hs
@@ -35,6 +35,13 @@
         showKey (Key ["boo"]) `shouldBe` "boo"
         showKey (Key ["foo","bar"]) `shouldBe` "foo.bar"
         showKey (Key ["baz","baz","quux"]) `shouldBe` "baz.baz.quux"
+  describe "displayMustacheWarning" $ do
+    it "renders “not found” warning correctly" $
+      displayMustacheWarning (MustacheVariableNotFound (Key ["foo"]))
+        `shouldBe` "Referenced value was not provided, key: foo"
+    it "renders “directly rendered value” warning correctly" $
+      displayMustacheWarning (MustacheDirectlyRenderedValue (Key ["foo"]))
+        `shouldBe` "Complex value rendered as such, key: foo"
 
 templateA :: Template
 templateA = Template "a" $ M.fromList
