diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.8
+-----------------------------------------------------------------------------
+- Update to `wai-predicates 0.6` and change default error renderer.
+- Update `bytestring-from` dependency.
+
 0.7
 -----------------------------------------------------------------------------
 - Update dependencies constraints.
diff --git a/bench/Bench.hs b/bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench.hs
@@ -0,0 +1,102 @@
+-- This Source Code Form is subject to the terms of the Mozilla Public
+-- License, v. 2.0. If a copy of the MPL was not distributed with this
+-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeOperators     #-}
+
+module Main (main) where
+
+import Criterion.Main
+import Criterion.Config
+import Network.HTTP.Types hiding (ok200)
+import Network.Wai
+import Network.Wai.Predicate
+import Network.Wai.Routing
+
+sitemap :: Routes a IO ()
+sitemap = do
+    get "/a" handlerA (query "foo")
+    get "/b" handlerB (query "foo" .&. query "bar")
+    get "/c" handlerC (query "foo" .&. query "bar" .&. query "baz")
+    get "/d" handlerD (query "foo" .&. query "bar" .&. query "baz" .&. query "zoo")
+    get "/z" handlerZ $
+          query "foo"
+      .&. query "bar"
+      .&. query "baz"
+      .&. query "zoo"
+      .&. query "x1"
+      .&. query "x2"
+      .&. query "x3"
+      .&. query "x4"
+      .&. query "x5"
+      .&. query "x6"
+      .&. query "x7"
+      .&. query "x8"
+
+handlerA :: Int -> IO Response
+handlerA _ = return ok200
+
+handlerB :: Int ::: Int -> IO Response
+handlerB _ = return ok200
+
+handlerC :: Int ::: Int ::: Int -> IO Response
+handlerC _ = return ok200
+
+handlerD :: Int ::: Int ::: Int ::: Int -> IO Response
+handlerD _ = return ok200
+
+handlerZ :: Int ::: Int ::: Int ::: Int ::: Int ::: Int ::: Int ::: Int ::: Int ::: Int ::: Int ::: Int -> IO Response
+handlerZ _ = return ok200
+
+ok200 :: Response
+ok200 = responseLBS status200 [] ""
+
+reqABad, reqBBad, reqCBad, reqDBad, reqZBad :: Request
+reqABad = defaultRequest { rawPathInfo = "/a" }
+reqBBad = reqAOk { rawPathInfo = "/b" }
+reqCBad = reqBOk { rawPathInfo = "/c" }
+reqDBad = reqCOk { rawPathInfo = "/d" }
+reqZBad = defaultRequest
+    { rawPathInfo = "/z"
+    , queryString =
+        [ ("foo", Just "42")
+        , ("bar", Just "42")
+        , ("naz", Just "42")
+        , ("zoo", Just "42")
+        , ("x1", Just "42")
+        , ("x2", Just "42")
+        , ("x3", Just "42")
+        , ("x4", Just "42")
+        , ("x5", Just "42")
+        , ("x6", Just "42")
+        , ("x7", Just "42")
+        ]
+    }
+
+reqAOk, reqBOk, reqCOk, reqDOk, reqZOk :: Request
+reqAOk = reqABad { queryString = [("foo", Just "42")] }
+reqBOk = reqBBad { queryString = ("bar", Just "100") : queryString reqAOk }
+reqCOk = reqCBad { queryString = ("baz", Just "0") : queryString reqBOk }
+reqDOk = reqDBad { queryString = ("zoo", Just "1") : queryString reqCOk }
+reqZOk = reqZBad { queryString = ("x8", Just "42") : queryString reqZBad }
+
+main :: IO ()
+main = defaultMainWith defaultConfig (return ())
+    [ bgroup "bench"
+        [ bench "a - ok"  (whnfIO $ f reqAOk)
+        , bench "a - bad" (whnfIO $ f reqABad)
+        , bench "b - ok"  (whnfIO $ f reqBOk)
+        , bench "b - bad" (whnfIO $ f reqBBad)
+        , bench "c - ok"  (whnfIO $ f reqCOk)
+        , bench "c - bad" (whnfIO $ f reqCBad)
+        , bench "d - ok"  (whnfIO $ f reqDOk)
+        , bench "d - bad" (whnfIO $ f reqDBad)
+        , bench "z - ok"  (whnfIO $ f reqZOk)
+        , bench "z - bad" (whnfIO $ f reqZBad)
+        ]
+    ]
+  where
+    f = route (prepare sitemap)
+
diff --git a/src/Network/Wai/Routing/Predicate.hs b/src/Network/Wai/Routing/Predicate.hs
--- a/src/Network/Wai/Routing/Predicate.hs
+++ b/src/Network/Wai/Routing/Predicate.hs
@@ -9,10 +9,9 @@
 -- @wai-predicates@.
 module Network.Wai.Routing.Predicate where
 
+import Control.Monad (when)
 import Data.ByteString (ByteString)
 import Data.ByteString.From
-import Data.Monoid
-import Network.HTTP.Types
 import Network.Wai.Predicate
 import Network.Wai.Predicate.Request
 import Network.Wai.Predicate.Utility
@@ -21,15 +20,16 @@
 -- | Request path parameters.
 capture :: (HasCaptures r, FromByteString a) => ByteString -> Predicate r Error a
 capture k r = case lookupCapture k r of
-    [] -> Fail (err status400 ("Missing path parameter '" <> k <> "'."))
-    cc -> either (Fail . err status400) return (readValues cc)
+    [] -> Fail $ e400 & addLabel "path" . setReason NotAvailable . setSource k
+    cc -> either (\m -> Fail $ e400 & addLabel "path" . setReason TypeError . setSource k . setMessage m)
+                 return
+                 (readValues cc)
 
 -- | Request path parameters.
 hasCapture :: (HasCaptures r) => ByteString -> Predicate r Error ()
 hasCapture k r =
-    if null (lookupCapture k r)
-        then Fail (err status400 ("Missing path parameter '" <> k <> "'."))
-        else return ()
+    when (null (lookupCapture k r)) $
+        Fail (e400 & addLabel "path" . setReason NotAvailable . setSource k)
 
 -- | @param \"foo\"@ is equivalent to @query \"foo\" .|. capture \"foo\"@
 param :: (HasCaptures r, HasQuery r, FromByteString a) => ByteString -> Predicate r Error a
diff --git a/src/Network/Wai/Routing/Route.hs b/src/Network/Wai/Routing/Route.hs
--- a/src/Network/Wai/Routing/Route.hs
+++ b/src/Network/Wai/Routing/Route.hs
@@ -34,7 +34,7 @@
 import Data.Either
 import Data.Function
 import Data.List hiding (head, delete)
-import Data.Maybe (fromMaybe, mapMaybe)
+import Data.Maybe (fromMaybe, mapMaybe, catMaybes)
 import Data.Monoid
 import Network.HTTP.Types
 import Network.Wai (Request, Response, responseLBS, responseBuilder, rawPathInfo)
@@ -78,6 +78,24 @@
 renderer :: Renderer -> Routes a m ()
 renderer f = Routes . modify $ \s -> s { renderfn = f }
 
+defRenderer :: Renderer
+defRenderer e =
+    let r = reason2str  <$> reason e
+        s = source2str  <$> source e
+        m = message2str <$> message e
+        l = labels2str . map Lazy.fromStrict $ labels e
+        x = case catMaybes [s, r, l] of
+               [] -> Nothing
+               xs -> Just (Lazy.intercalate " " xs)
+    in maybe x (\y -> (<> (" -- " <> y)) <$> x) m
+  where
+    reason2str  NotAvailable = "not-available"
+    reason2str  TypeError    = "type-error"
+    source2str  s  = "'" <> Lazy.fromStrict s <> "'"
+    message2str s  = Lazy.fromStrict s
+    labels2str  [] = Nothing
+    labels2str  xs = Just $ "[" <> Lazy.intercalate "," xs <> "]"
+
 -- | The Routes monad state type.
 data St a m = St
     { routes   :: [Route a m]
@@ -86,7 +104,7 @@
 
 -- | Initial state.
 zero :: St a m
-zero = St [] (fmap Lazy.fromStrict . message)
+zero = St [] defRenderer
 
 -- | The Routes monad is used to add routing declarations
 -- via 'addRoute' or one of 'get', 'post', etc.
@@ -193,7 +211,7 @@
 select render rr req = do
     let ms = filter ((method req ==) . _method) rr
     if null ms
-        then return $ respond render (Error status405 Nothing) [(allow, validMethods)]
+        then return $ respond render e405 [(allow, validMethods)]
         else evalAll ms
   where
     allow :: HeaderName
diff --git a/test/TestSuite.hs b/test/TestSuite.hs
--- a/test/TestSuite.hs
+++ b/test/TestSuite.hs
@@ -1,3 +1,7 @@
+-- This Source Code Form is subject to the terms of the Mozilla Public
+-- License, v. 2.0. If a copy of the MPL was not distributed with this
+-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
 module Main where
 
 import Test.Tasty
diff --git a/test/Tests/Wai/Route.hs b/test/Tests/Wai/Route.hs
--- a/test/Tests/Wai/Route.hs
+++ b/test/Tests/Wai/Route.hs
@@ -1,3 +1,7 @@
+-- This Source Code Form is subject to the terms of the Mozilla Public
+-- License, v. 2.0. If a copy of the MPL was not distributed with this
+-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
 {-# LANGUAGE DataKinds         #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeOperators     #-}
@@ -131,11 +135,11 @@
 
     rs0 <- f rq
     status400 @=? responseStatus rs0
-    "Missing query 'baz'." @=? responseBody rs0
+    "'baz' not-available [query]" @=? responseBody rs0
 
     rs1 <- f . withQuery "baz" "abc" $ rq
     status400 @=? responseStatus rs1
-    "Failed reading: Invalid Int" @=? responseBody rs1
+    "'baz' type-error [query] -- Failed reading: Invalid Int" @=? responseBody rs1
 
     rs2 <- f . withQuery "baz" "abc" . withQuery "baz" "123" $ rq
     status200 @=? responseStatus rs2
@@ -155,7 +159,8 @@
     "Just 123" @=? responseBody rs1
 
     rs2 <- f . withQuery "foo" "abc" $ rq
-    status200 @=? responseStatus rs2
+    status400 @=? responseStatus rs2
+    "'foo' type-error [query] -- Failed reading: Invalid Int" @=? responseBody rs2
 
 
 testEndpointD :: Application -> Assertion
@@ -171,8 +176,8 @@
     "42"      @=? responseBody rs1
 
     rs2 <- f . withQuery "foo" "yyy" $ rq
-    status200 @=? responseStatus rs2
-    "0"       @=? responseBody rs2
+    status400 @=? responseStatus rs2
+    "'foo' type-error [query] -- Failed reading: Invalid Int" @=? responseBody rs2
 
 
 testEndpointE :: Application -> Assertion
@@ -188,8 +193,8 @@
     "42"      @=? responseBody rs1
 
     rs2 <- f $ withHeader "foo" "abc" rq
-    status200 @=? responseStatus rs2
-    "0"       @=? responseBody rs2
+    status400 @=? responseStatus rs2
+    "'foo' type-error [header] -- Failed reading: Invalid Int" @=? responseBody rs2
 
 
 testEndpointF :: Application -> Assertion
@@ -207,11 +212,11 @@
 
     rs0 <- f rq
     status400 @=? responseStatus rs0
-    "Missing cookie 'user'." @=? responseBody rs0
+    "'user' not-available [cookie]" @=? responseBody rs0
 
     rs1 <- f . withHeader "Cookie" "user=joe" $ rq
     status400 @=? responseStatus rs1
-    "Missing cookie 'age'." @=? responseBody rs1
+    "'age' not-available [cookie]" @=? responseBody rs1
 
     rs2 <- f . withHeader "Cookie" "user=joe; age=42" $ rq
     status200 @=? responseStatus rs2
diff --git a/wai-routing.cabal b/wai-routing.cabal
--- a/wai-routing.cabal
+++ b/wai-routing.cabal
@@ -1,5 +1,5 @@
 name:                wai-routing
-version:             0.7
+version:             0.8
 synopsis:            Declarative routing for WAI.
 license:             OtherLicense
 license-file:        LICENSE
@@ -79,13 +79,13 @@
         attoparsec       >= 0.10  && < 0.12
       , base             == 4.*
       , bytestring       >= 0.9   && < 0.11
-      , bytestring-from  == 0.2.*
+      , bytestring-from  >= 0.2   && < 0.4
       , cookie           == 0.4.*
       , case-insensitive >= 1.1   && < 1.3
       , http-types       == 0.8.*
       , transformers     >= 0.3   && < 0.5
       , wai              >= 2.0   && < 2.2
-      , wai-predicates   >= 0.3.1 && < 0.6
+      , wai-predicates   >= 0.6   && < 0.7
       , wai-route        == 0.1.*
 
 test-suite wai-routing-tests
@@ -111,6 +111,20 @@
       , tasty            >= 0.8
       , tasty-hunit      >= 0.8
       , tasty-quickcheck >= 0.8
+      , wai
+      , wai-predicates
+      , wai-routing
+
+benchmark wai-routing-bench
+    type:             exitcode-stdio-1.0
+    default-language: Haskell2010
+    main-is:          Bench.hs
+    hs-source-dirs:   bench
+    ghc-options:      -Wall -O2 -fwarn-tabs
+    build-depends:
+        base          == 4.*
+      , criterion     == 0.8.*
+      , http-types
       , wai
       , wai-predicates
       , wai-routing
