diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for config-schema
 
+## 0.4.1.0
+
+* Add `loadValueFromFile` and `SchemaError`. This is intended
+  as a quick way to get a configuration file loaded with all
+  errors being thrown as exceptions.
+
 ## 0.4.0.0
 
 * Parameterize the Load module on a position type
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,6 +3,14 @@
 
 [![Hackage](https://img.shields.io/hackage/v/config-schema.svg)](https://hackage.haskell.org/package/config-schema) [![Build Status](https://secure.travis-ci.org/glguy/config-schema.png?branch=master)](http://travis-ci.org/glguy/config-schema)
 
+Live Demo
+--------
+
+The config-value and config-schema packages are available in a [live demo](https://glguy.net/config-demo/).
+
+About
+--------
+
 This package allows the user to define configuration schemas suitable for
 matching against configuration files written in the
 [config-value](https://hackage.haskell.org/package/config-value) format.
diff --git a/config-schema.cabal b/config-schema.cabal
--- a/config-schema.cabal
+++ b/config-schema.cabal
@@ -1,5 +1,5 @@
 name:                config-schema
-version:             0.4.0.0
+version:             0.4.1.0
 synopsis:            Schema definitions for the config-value package
 description:         This package makes it possible to defined schemas for use when
                      loading configuration files using the config-value format.
diff --git a/src/Config/Schema/Load.hs b/src/Config/Schema/Load.hs
--- a/src/Config/Schema/Load.hs
+++ b/src/Config/Schema/Load.hs
@@ -12,12 +12,15 @@
 -}
 module Config.Schema.Load
   ( loadValue
+  , loadValueFromFile
 
   -- * Errors
+  , SchemaError(..)
   , LoadError(..)
   , Problem(..)
   ) where
 
+import           Control.Exception                (Exception(..), throwIO)
 import           Control.Monad                    (zipWithM)
 import           Control.Monad.Trans.Class        (lift)
 import           Control.Monad.Trans.State        (StateT(..), runStateT)
@@ -31,6 +34,7 @@
 import qualified Data.List.NonEmpty as NonEmpty
 import           Data.Text                        (Text)
 import qualified Data.Text as Text
+import qualified Data.Text.IO as Text
 
 import           Config
 import           Config.Schema.Spec
@@ -46,6 +50,47 @@
 loadValue spec val = runLoad (getValue spec val)
 
 
+-- | Read a configuration file, parse it, and validate it according
+-- to the given specification.
+--
+-- Throws 'IOError', 'ParseError', or 'SchemaError'
+loadValueFromFile ::
+  FilePath     {- ^ filename      -} ->
+  ValueSpecs a {- ^ specification -} ->
+  IO a
+loadValueFromFile path spec =
+  do txt <- Text.readFile path
+     val <- either throwIO return (parse txt)
+     either (throwIO . SchemaError) return (loadValue spec val)
+
+
+-- | Newtype wrapper for schema load errors.
+newtype SchemaError = SchemaError (NonEmpty (LoadError Position))
+  deriving Show
+
+-- | Custom 'displayException' implementation
+instance Exception SchemaError where
+  displayException (SchemaError e) = foldr showLoadError "" e
+    where
+      showLoadError (LoadError pos path problem)
+        = shows (posLine pos)
+        . showChar ':'
+        . shows (posColumn pos)
+        . showString ": "
+        . foldr (\x xs -> showString (Text.unpack x) . showChar ':' . xs) id path
+        . showChar ' '
+        . showProblem problem
+        . showChar '\n'
+
+      showProblem p =
+        case p of
+          MissingSection x -> showString "missing required section `"
+                            . showString (Text.unpack x) . showChar '`'
+          UnusedSection  x -> showString "unused section `"
+                            . showString (Text.unpack x) . showChar '`'
+          SpecMismatch   x -> showString "expected " . showString (Text.unpack x)
+
+
 getSection :: p -> SectionSpec a -> StateT [Section p] (Load p) a
 getSection pos (ReqSection k _ w) =
   do v <- StateT (lookupSection pos k)
@@ -102,7 +147,7 @@
 -- against the given specification and associates them with the
 -- section name.
 getAssoc :: ValueSpecs a -> [Section p] -> Load p [(Text,a)]
-getAssoc w = traverse $ \(Section _ k v) -> (,) k <$> getValue w v
+getAssoc w = traverse $ \(Section _ k v) -> (,) k <$> scope k (getValue w v)
 
 
 -- | Match a value against its specification. If 'Just' is matched
