diff --git a/driver/Main.hs b/driver/Main.hs
--- a/driver/Main.hs
+++ b/driver/Main.hs
@@ -4,6 +4,7 @@
 import           Prelude.Compat
 import           Control.Monad.Compat
 import           Control.Exception
+import           System.IO
 import           System.IO.Error
 import           Data.List.Compat
 import           Data.Version (showVersion)
@@ -12,8 +13,8 @@
 import           Paths_hpack (version)
 import           Run
 
-header :: String
-header = unlines [
+header :: String -> String
+header configFile = unlines [
     "-- This file has been generated from " ++ configFile ++ " by hpack version " ++ showVersion version ++ "."
   , "--"
   , "-- see: https://github.com/sol/hpack"
@@ -22,9 +23,10 @@
 
 main :: IO ()
 main = do
-  (name, new) <- run
+  (configFile, warnings, name, new) <- run
+  forM_ warnings $ \warning -> hPutStrLn stderr ("WARNING: " ++ warning)
   old <- force . either (const Nothing) (Just . stripHeader) <$> tryJust (guard . isDoesNotExistError) (readFile name)
-  unless (old == Just (lines new)) (writeFile name $ header ++ new)
+  unless (old == Just (lines new)) (writeFile name $ header configFile ++ new)
   where
     stripHeader :: String -> [String]
     stripHeader = dropWhile null . dropWhile ("--" `isPrefixOf`) . lines
diff --git a/hpack.cabal b/hpack.cabal
--- a/hpack.cabal
+++ b/hpack.cabal
@@ -1,9 +1,9 @@
--- This file has been generated from package.yaml by hpack version 0.1.1.
+-- This file has been generated from package.yml by hpack version 0.2.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hpack
-version:        0.1.2
+version:        0.2.0
 synopsis:       An alternative format for Haskell packages
 homepage:       https://github.com/sol/hpack#readme
 bug-reports:    https://github.com/sol/hpack/issues
@@ -18,8 +18,12 @@
   location: https://github.com/sol/hpack
 
 executable hpack
-  hs-source-dirs: driver, src
+  hs-source-dirs: src, driver
   main-is: Main.hs
+  other-modules:
+      Config
+      Run
+      Util
   build-depends:
       aeson >= 0.8
     , base == 4.*
@@ -27,6 +31,7 @@
     , deepseq
     , directory
     , filepath
+    , text
     , unordered-containers
     , yaml
   ghc-options: -Wall
@@ -34,16 +39,16 @@
 
 test-suite spec
   type: exitcode-stdio-1.0
-  hs-source-dirs: test, src
+  hs-source-dirs: src, test
   main-is: Spec.hs
   other-modules:
+      Config
+      Run
+      Util
       ConfigSpec
       Helper
       RunSpec
       UtilSpec
-      Config
-      Run
-      Util
   build-depends:
       aeson >= 0.8
     , base == 4.*
@@ -51,6 +56,7 @@
     , deepseq
     , directory
     , filepath
+    , text
     , unordered-containers
     , yaml
 
diff --git a/src/Config.hs b/src/Config.hs
--- a/src/Config.hs
+++ b/src/Config.hs
@@ -1,4 +1,8 @@
-{-# LANGUAGE DeriveGeneric, RecordWildCards #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 module Config (
   readPackageConfig
 , Package(..)
@@ -12,18 +16,47 @@
 import           Prelude.Compat
 import           Control.Applicative
 import           Control.Monad.Compat
-import           Data.List ((\\))
+import           Data.List (nub, sort, (\\))
 import           Data.String
 import           Data.Maybe
 import           Data.Yaml
 import           GHC.Generics
 import           Data.HashMap.Lazy (HashMap)
 import qualified Data.HashMap.Lazy as Map
+import qualified Data.Text as T
 import           System.FilePath
 import           System.Directory
+import           Data.Data
+import           Data.Aeson.Types
 
 import           Util
 
+genericParseJSON_ :: forall a. (Typeable a, Generic a, GFromJSON (Rep a)) => Value -> Parser a
+genericParseJSON_ = genericParseJSON defaultOptions {fieldLabelModifier = hyphenize name}
+  where
+    name = (tyConName . typeRepTyCon . typeRep) (Proxy :: Proxy a)
+
+hyphenize :: String -> String -> String
+hyphenize name = camelTo '-' . drop (length name)
+
+data CaptureUnknownFields a = CaptureUnknownFields {
+  captureUnknownFieldsFields :: [String]
+, captureUnknownFieldsValue :: a
+} deriving (Eq, Show, Generic, Data, Typeable)
+
+instance (Data a, FromJSON a) => FromJSON (CaptureUnknownFields a) where
+  parseJSON v = captureUnknownFields <$> parseJSON v
+    where
+      captureUnknownFields a = case v of
+        Object o -> CaptureUnknownFields unknown a
+          where
+            unknown = keys \\ fields
+            keys = map T.unpack (Map.keys o)
+            constr = toConstr a
+            name = showConstr constr
+            fields = map (hyphenize name) (constrFields constr)
+        _ -> CaptureUnknownFields [] a
+
 data LibrarySection = LibrarySection {
   librarySectionSourceDirs :: Maybe (List FilePath)
 , librarySectionExposedModules :: Maybe (List String)
@@ -31,10 +64,10 @@
 , librarySectionDependencies :: Maybe (List Dependency)
 , librarySectionDefaultExtensions :: Maybe (List String)
 , librarySectionGhcOptions :: Maybe (List GhcOption)
-} deriving (Eq, Show, Generic)
+} deriving (Eq, Show, Generic, Data, Typeable)
 
 instance FromJSON LibrarySection where
-  parseJSON = genericParseJSON_ "LibrarySection"
+  parseJSON = genericParseJSON_
 
 data ExecutableSection = ExecutableSection {
   executableSectionMain :: FilePath
@@ -43,10 +76,10 @@
 , executableSectionDependencies :: Maybe (List Dependency)
 , executableSectionDefaultExtensions :: Maybe (List String)
 , executableSectionGhcOptions :: Maybe (List GhcOption)
-} deriving (Eq, Show, Generic)
+} deriving (Eq, Show, Generic, Data, Typeable)
 
 instance FromJSON ExecutableSection where
-  parseJSON = genericParseJSON_ "ExecutableSection"
+  parseJSON = genericParseJSON_
 
 data PackageConfig = PackageConfig {
   packageConfigName :: Maybe String
@@ -67,13 +100,13 @@
 , packageConfigDependencies :: Maybe (List Dependency)
 , packageConfigDefaultExtensions :: Maybe (List String)
 , packageConfigGhcOptions :: Maybe (List GhcOption)
-, packageConfigLibrary :: Maybe LibrarySection
-, packageConfigExecutables :: Maybe (HashMap String ExecutableSection)
-, packageConfigTests :: Maybe (HashMap String ExecutableSection)
-} deriving (Eq, Show, Generic)
+, packageConfigLibrary :: Maybe (CaptureUnknownFields LibrarySection)
+, packageConfigExecutables :: Maybe (HashMap String (CaptureUnknownFields ExecutableSection))
+, packageConfigTests :: Maybe (HashMap String (CaptureUnknownFields ExecutableSection))
+} deriving (Eq, Show, Generic, Data, Typeable)
 
 instance FromJSON PackageConfig where
-  parseJSON value = handleNullValues <$> genericParseJSON_ "PackageConfig" value
+  parseJSON value = handleNullValues <$> genericParseJSON_ value
     where
       handleNullValues :: PackageConfig -> PackageConfig
       handleNullValues =
@@ -92,14 +125,16 @@
   where
     p = parseJSON >=> (.: fromString name)
 
-readPackageConfig :: FilePath -> IO (Either String Package)
+readPackageConfig :: FilePath -> IO (Either String ([String], Package))
 readPackageConfig file = do
   config <- decodeFileEither file
   either (return . Left . errToString) (fmap Right . mkPackage) config
   where
     errToString err = file ++ case err of
       AesonException e -> ": " ++ e
-      InvalidYaml (Just e) -> let loc = yamlProblemMark e in ":" ++ show (yamlLine loc) ++ ":" ++ show (yamlColumn loc) ++ ": " ++ yamlProblem e ++ " " ++ yamlContext e
+      InvalidYaml (Just (YamlException s)) -> ": " ++ s
+      InvalidYaml (Just (YamlParseException{..})) -> ":" ++ show yamlLine ++ ":" ++ show yamlColumn ++ ": " ++ yamlProblem ++ " " ++ yamlContext
+        where YamlMark{..} = yamlProblemMark
       _ -> ": " ++ show err
 
 type Dependency = String
@@ -145,20 +180,28 @@
 , executableGhcOptions :: [GhcOption]
 } deriving (Eq, Show)
 
-mkPackage :: PackageConfig -> IO Package
-mkPackage PackageConfig{..} = do
+mkPackage :: (CaptureUnknownFields PackageConfig) -> IO ([String], Package)
+mkPackage (CaptureUnknownFields unknownFields PackageConfig{..}) = do
   let dependencies = fromMaybeList packageConfigDependencies
-  let sourceDirs = fromMaybeList packageConfigSourceDirs
-  let defaultExtensions = fromMaybeList packageConfigDefaultExtensions
-  let ghcOptions = fromMaybeList packageConfigGhcOptions
-  mLibrary <- mapM (mkLibrary sourceDirs dependencies defaultExtensions ghcOptions) packageConfigLibrary
-  executables <- toExecutables sourceDirs dependencies defaultExtensions ghcOptions packageConfigExecutables
-  tests <- toExecutables sourceDirs dependencies defaultExtensions ghcOptions packageConfigTests
+      sourceDirs = fromMaybeList packageConfigSourceDirs
+      defaultExtensions = fromMaybeList packageConfigDefaultExtensions
+      ghcOptions = fromMaybeList packageConfigGhcOptions
+      convert f = f sourceDirs dependencies defaultExtensions ghcOptions
 
+  mLibrary <- mapM (convert toLibrary) mLibrarySection
+  executables <- convert toExecutables mExecutableSections
+  tests <- convert toExecutables mTestSections
+
   name <- maybe (takeBaseName <$> getCurrentDirectory) return packageConfigName
 
   licenseFileExists <- doesFileExist "LICENSE"
 
+  missingSourceDirs <- nub . sort <$> filterM (fmap not <$> doesDirectoryExist) (
+       maybe [] librarySourceDirs mLibrary
+    ++ concatMap executableSourceDirs executables
+    ++ concatMap executableSourceDirs tests
+    )
+
   let package = Package {
         packageName = name
       , packageVersion = fromMaybe "0.0.0" packageConfigVersion
@@ -179,8 +222,38 @@
       , packageExecutables = executables
       , packageTests = tests
       }
-  return package
+
+      warnings =
+           formatUnknownFields "package description" unknownFields
+        ++ maybe [] (formatUnknownFields "library section") (captureUnknownFieldsFields <$> packageConfigLibrary)
+        ++ formatUnknownSectionFields "executable" packageConfigExecutables
+        ++ formatUnknownSectionFields "test" packageConfigTests
+        ++ formatMissingSourceDirs missingSourceDirs
+
+  return (warnings, package)
   where
+    mLibrarySection :: Maybe LibrarySection
+    mLibrarySection = captureUnknownFieldsValue <$> packageConfigLibrary
+
+    mExecutableSections :: Maybe (HashMap String ExecutableSection)
+    mExecutableSections = fmap captureUnknownFieldsValue <$> packageConfigExecutables
+
+    mTestSections :: Maybe (HashMap String ExecutableSection)
+    mTestSections = fmap captureUnknownFieldsValue <$> packageConfigTests
+
+    formatUnknownFields name = map f . sort
+      where
+        f field = "Ignoring unknown field " ++ show field ++ " in " ++ name
+
+    formatUnknownSectionFields sectionType = maybe [] (concatMap f . Map.toList . fmap captureUnknownFieldsFields)
+      where
+        f :: (String, [String]) -> [String]
+        f (section, fields) = formatUnknownFields (sectionType ++ " section " ++ show section) fields
+
+    formatMissingSourceDirs = map f
+      where
+        f name = "Specified source-dir " ++ show name ++ " does not exist"
+
     github = ("https://github.com/" ++) <$> packageConfigGithub
 
     homepage :: Maybe String
@@ -197,8 +270,8 @@
       where
         fromGithub = ((++ "/issues") <$> github)
 
-mkLibrary :: [FilePath] -> [Dependency] -> [String] -> [GhcOption] -> LibrarySection -> IO Library
-mkLibrary globalSourceDirs globalDependencies globalDefaultExtensions globalGhcOptions LibrarySection{..} = do
+toLibrary :: [FilePath] -> [Dependency] -> [String] -> [GhcOption] -> LibrarySection -> IO Library
+toLibrary globalSourceDirs globalDependencies globalDefaultExtensions globalGhcOptions LibrarySection{..} = do
   modules <- concat <$> mapM getModules sourceDirs
 
   let (exposedModules, otherModules) = determineModules modules librarySectionExposedModules librarySectionOtherModules
diff --git a/src/Run.hs b/src/Run.hs
--- a/src/Run.hs
+++ b/src/Run.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE QuasiQuotes, RecordWildCards #-}
 module Run (
   run
-, configFile
 -- exported for testing
 , renderPackage
 ) where
@@ -16,20 +15,20 @@
 import           Config
 
 configFile :: FilePath
-configFile = "package.yaml"
+configFile = "package.yml"
 
-run :: IO (FilePath, String)
+run :: IO (FilePath, [String], FilePath, String)
 run = do
   mPackage <- readPackageConfig configFile
   case mPackage of
-    Right package -> do
+    Right (warnings, package) -> do
       let cabalFile = packageName package ++ ".cabal"
 
       old <- tryReadFile cabalFile
 
       let alignment = fromMaybe 16 (old >>= sniffAlignment)
           output = renderPackage alignment (maybe [] extractFieldOrderHint old) package
-      return (cabalFile, output)
+      return (configFile, warnings, cabalFile, output)
     Left err -> die err
 
 renderPackage :: Int -> [String] -> Package -> String
diff --git a/src/Util.hs b/src/Util.hs
--- a/src/Util.hs
+++ b/src/Util.hs
@@ -1,8 +1,7 @@
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE DeriveDataTypeable #-}
 module Util (
   List(..)
 , toModule
-, genericParseJSON_
 , getFilesRecursive
 , tryReadFile
 , sniffAlignment
@@ -21,15 +20,12 @@
 import           Data.List
 import           System.Directory
 import           System.FilePath
+import           Data.Data
 
-import           GHC.Generics
 import           Data.Aeson.Types
 
-genericParseJSON_ :: (Generic a, GFromJSON (Rep a)) => String -> Value -> Parser a
-genericParseJSON_ name = genericParseJSON defaultOptions {fieldLabelModifier = camelTo '-' . drop (length name)}
-
 newtype List a = List {fromList :: [a]}
-  deriving (Eq, Show)
+  deriving (Eq, Show, Data, Typeable)
 
 instance FromJSON a => FromJSON (List a) where
   parseJSON v = List <$> (parseJSON v <|> (return <$> parseJSON v))
diff --git a/test/ConfigSpec.hs b/test/ConfigSpec.hs
--- a/test/ConfigSpec.hs
+++ b/test/ConfigSpec.hs
@@ -29,233 +29,279 @@
 spec :: Spec
 spec = around_ (inTempDirectoryNamed "foo") $ do
   describe "readPackageConfig" $ do
+    it "warns on unknown fields" $ do
+      writeFile "package.yml" [i|
+        bar: 23
+        baz: 42
+        |]
+      fmap fst <$> readPackageConfig "package.yml" `shouldReturn` Right [
+          "Ignoring unknown field \"bar\" in package description"
+        , "Ignoring unknown field \"baz\" in package description"
+        ]
+
     it "accepts name" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         name: bar
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageName = "bar"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageName = "bar"}
 
     it "accepts version" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         version: 0.1.0
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageVersion = "0.1.0"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageVersion = "0.1.0"}
 
     it "accepts synopsis" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         synopsis: some synopsis
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageSynopsis = Just "some synopsis"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageSynopsis = Just "some synopsis"}
 
     it "accepts description" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         description: some description
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageDescription = Just "some description"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageDescription = Just "some description"}
 
     it "accepts category" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         category: Data
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageCategory = Just "Data"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageCategory = Just "Data"}
 
     it "accepts author" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         author: John Doe
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageAuthor = ["John Doe"]}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageAuthor = ["John Doe"]}
 
     it "accepts maintainer" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         maintainer: John Doe <john.doe@example.com>
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageMaintainer = ["John Doe <john.doe@example.com>"]}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageMaintainer = ["John Doe <john.doe@example.com>"]}
 
     it "accepts copyright" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         copyright: (c) 2015 John Doe
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageCopyright = ["(c) 2015 John Doe"]}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageCopyright = ["(c) 2015 John Doe"]}
 
     it "accepts stability" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         stability: experimental
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageStability c `shouldBe` Just "experimental"
 
     it "accepts homepage URL" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         homepage: https://example.com/
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageHomepage c `shouldBe` Just "https://example.com/"
 
     it "infers homepage URL from github" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageHomepage c `shouldBe` Just "https://github.com/hspec/hspec#readme"
 
     it "omits homepage URL if it is null" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         homepage: null
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageHomepage c `shouldBe` Nothing
 
     it "accepts bug-reports URL" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         bug-reports: https://example.com/issues
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageBugReports c `shouldBe` Just "https://example.com/issues"
 
     it "infers bug-reports URL from github" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageBugReports c `shouldBe` Just "https://github.com/hspec/hspec/issues"
 
     it "omits bug-reports URL if it is null" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         bug-reports: null
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageBugReports c `shouldBe` Nothing
 
     it "accepts license" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         license: MIT
         |]
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageLicense = Just "MIT"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageLicense = Just "MIT"}
 
     it "infers license file" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         name: foo
         |]
       touch "LICENSE"
-      readPackageConfig "package.yaml" `shouldReturn` Right package {packageLicenseFile = Just "LICENSE"}
+      Right (_, c) <- readPackageConfig "package.yml"
+      c `shouldBe` package {packageLicenseFile = Just "LICENSE"}
 
     it "accepts extra-source-files" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         extra-source-files:
           - CHANGES.markdown
           - README.markdown
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageExtraSourceFiles c `shouldBe` ["CHANGES.markdown", "README.markdown"]
 
     it "accepts github" $ do
-      writeFile "package.yaml" [i|
+      writeFile "package.yml" [i|
         github: hspec/hspec
         |]
-      Right c <- readPackageConfig "package.yaml"
+      Right (_, c) <- readPackageConfig "package.yml"
       packageSourceRepository c `shouldBe` Just "https://github.com/hspec/hspec"
 
     context "when reading library section" $ do
+      it "warns on unknown fields" $ do
+        writeFile "package.yml" [i|
+          library:
+            bar: 23
+            baz: 42
+          |]
+
+        fmap fst <$> readPackageConfig "package.yml" `shouldReturn` Right [
+            "Ignoring unknown field \"bar\" in library section"
+          , "Ignoring unknown field \"baz\" in library section"
+          ]
+
       it "accepts source-dirs" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           library:
             source-dirs:
               - foo
               - bar
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {librarySourceDirs = ["foo", "bar"]}
 
       it "accepts default-extensions" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           library:
             default-extensions:
               - Foo
               - Bar
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {libraryDefaultExtensions = ["Foo", "Bar"]}
 
       it "accepts global default-extensions" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           default-extensions:
             - Foo
             - Bar
           library: {}
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {libraryDefaultExtensions = ["Foo", "Bar"]}
 
       it "accepts global source-dirs" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           source-dirs:
             - foo
             - bar
           library: {}
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {librarySourceDirs = ["foo", "bar"]}
 
       it "allows to specify exposed-modules" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           library:
             source-dirs: src
             exposed-modules: Foo
           |]
         touch "src/Foo.hs"
         touch "src/Bar.hs"
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {librarySourceDirs = ["src"], libraryExposedModules = ["Foo"], libraryOtherModules = ["Bar"]}
 
       it "allows to specify other-modules" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           library:
             source-dirs: src
             other-modules: Bar
           |]
         touch "src/Foo.hs"
         touch "src/Bar.hs"
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {librarySourceDirs = ["src"], libraryExposedModules = ["Foo"], libraryOtherModules = ["Bar"]}
 
       it "allows to specify both exposed-modules and other-modules" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           library:
             source-dirs: src
             exposed-modules: Foo
             other-modules: Bar
           |]
         touch "src/Baz.hs"
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageLibrary c `shouldBe` Just library {librarySourceDirs = ["src"], libraryExposedModules = ["Foo"], libraryOtherModules = ["Bar"]}
 
       context "when neither exposed-module nor other-module are specified" $ do
         it "exposes all modules" $ do
-          writeFile "package.yaml" [i|
+          writeFile "package.yml" [i|
             library:
               source-dirs: src
             |]
           touch "src/Foo.hs"
           touch "src/Bar.hs"
-          Right c <- readPackageConfig "package.yaml"
+          Right (_, c) <- readPackageConfig "package.yml"
           packageLibrary c `shouldBe` Just library {librarySourceDirs = ["src"], libraryExposedModules = ["Bar", "Foo"]}
 
     context "when reading executable section" $ do
+      it "warns on unknown fields" $ do
+        writeFile "package.yml" [i|
+          executables:
+            foo:
+              main: Main.hs
+              bar: 42
+              baz: 23
+          |]
+
+        fmap fst <$> readPackageConfig "package.yml" `shouldReturn` Right [
+            "Ignoring unknown field \"bar\" in executable section \"foo\""
+          , "Ignoring unknown field \"baz\" in executable section \"foo\""
+          ]
+
       it "reads executable section" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               main: driver/Main.hs
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageExecutables c `shouldBe` [executable "foo" "driver/Main.hs"]
 
       it "accepts source-dirs" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               main: Main.hs
@@ -263,11 +309,11 @@
                 - foo
                 - bar
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageExecutables c `shouldBe` [(executable "foo" "Main.hs") {executableSourceDirs = ["foo", "bar"]}]
 
       it "accepts global source-dirs" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           source-dirs:
             - foo
             - bar
@@ -275,7 +321,7 @@
             foo:
               main: Main.hs
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageExecutables c `shouldBe` [(executable "foo" "Main.hs") {executableSourceDirs = ["foo", "bar"]}]
 
       it "infers other-modules" $ do
@@ -283,30 +329,30 @@
         touch "src/Foo.hs"
         touch "src/Bar.hs"
         touch "src/Baz.lhs"
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               main: Main.hs
               source-dirs: src
           |]
-        Right [r] <- fmap packageExecutables <$> readPackageConfig "package.yaml"
+        Right (_, [r]) <- (fmap . fmap) packageExecutables <$> readPackageConfig "package.yml"
         executableOtherModules r `shouldBe` ["Bar", "Baz", "Foo"]
 
       it "allows to specify other-modules" $ do
         touch "src/Foo.hs"
         touch "src/Bar.hs"
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               main: Main.hs
               source-dirs: src
               other-modules: Baz
           |]
-        Right [r] <- fmap packageExecutables <$> readPackageConfig "package.yaml"
+        Right (_, [r]) <- (fmap . fmap) packageExecutables <$> readPackageConfig "package.yml"
         executableOtherModules r `shouldBe` ["Baz"]
 
       it "accepts default-extensions" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               main: driver/Main.hs
@@ -314,11 +360,11 @@
                 - Foo
                 - Bar
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageExecutables c `shouldBe` [(executable "foo" "driver/Main.hs") {executableDefaultExtensions = ["Foo", "Bar"]}]
 
       it "accepts global default-extensions" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           default-extensions:
             - Foo
             - Bar
@@ -326,47 +372,65 @@
             foo:
               main: driver/Main.hs
           |]
-        Right c <- readPackageConfig "package.yaml"
+        Right (_, c) <- readPackageConfig "package.yml"
         packageExecutables c `shouldBe` [(executable "foo" "driver/Main.hs") {executableDefaultExtensions = ["Foo", "Bar"]}]
 
       it "accepts GHC options" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               main: driver/Main.hs
               ghc-options: -Wall
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Right package {packageExecutables = [(executable "foo" "driver/Main.hs") {executableGhcOptions = ["-Wall"]}]}
+        Right (_, c) <- readPackageConfig "package.yml"
+        c `shouldBe` package {packageExecutables = [(executable "foo" "driver/Main.hs") {executableGhcOptions = ["-Wall"]}]}
 
       it "accepts global GHC options" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           ghc-options: -Wall
           executables:
             foo:
               main: driver/Main.hs
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Right package {packageExecutables = [(executable "foo" "driver/Main.hs") {executableGhcOptions = ["-Wall"]}]}
+        Right (_, c) <- readPackageConfig "package.yml"
+        c `shouldBe` package {packageExecutables = [(executable "foo" "driver/Main.hs") {executableGhcOptions = ["-Wall"]}]}
 
     context "when reading test section" $ do
+      it "warns on unknown fields" $ do
+        writeFile "package.yml" [i|
+          tests:
+            foo:
+              main: Main.hs
+              bar: 42
+              baz: 23
+          |]
+
+        fmap fst <$> readPackageConfig "package.yml" `shouldReturn` Right [
+            "Ignoring unknown field \"bar\" in test section \"foo\""
+          , "Ignoring unknown field \"baz\" in test section \"foo\""
+          ]
+
       it "reads test section" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           tests:
             spec:
               main: test/Spec.hs
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Right package {packageTests = [executable "spec" "test/Spec.hs"]}
+        Right (_, c) <- readPackageConfig "package.yml"
+        c `shouldBe` package {packageTests = [executable "spec" "test/Spec.hs"]}
 
       it "accepts single dependency" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           tests:
             spec:
               main: test/Spec.hs
               dependencies: hspec
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Right package {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = [["hspec"]]}]}
+        Right (_, c) <- readPackageConfig "package.yml"
+        c `shouldBe` package {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = [["hspec"]]}]}
 
       it "accepts list of dependencies" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           tests:
             spec:
               main: test/Spec.hs
@@ -374,11 +438,12 @@
                 - hspec
                 - QuickCheck
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Right package {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = [["hspec", "QuickCheck"]]}]}
+        Right (_, c) <- readPackageConfig "package.yml"
+        c `shouldBe` package {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = [["hspec", "QuickCheck"]]}]}
 
       context "when both top-level and section specific dependencies are specified" $ do
         it "combines dependencies" $ do
-          writeFile "package.yaml" [i|
+          writeFile "package.yml" [i|
             dependencies:
               - base
 
@@ -387,21 +452,51 @@
                 main: test/Spec.hs
                 dependencies: hspec
             |]
-          readPackageConfig "package.yaml" `shouldReturn` Right package {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = [["base"], ["hspec"]]}]}
+          Right (_, c) <- readPackageConfig "package.yml"
+          c `shouldBe` package {packageTests = [(executable "spec" "test/Spec.hs") {executableDependencies = [["base"], ["hspec"]]}]}
 
-    context "when package.yaml can not be parsed" $ do
+    context "when a specified source directory does not exist" $ do
+      it "warns" $ do
+        writeFile "package.yml" [i|
+          source-dirs:
+            - some-dir
+            - some-existing-dir
+          library:
+            source-dirs: some-lib-dir
+          executables:
+            main:
+              main: Main.hs
+              source-dirs: some-exec-dir
+          tests:
+            spec:
+              main: Main.hs
+              source-dirs: some-test-dir
+          |]
+        touch "some-existing-dir/foo"
+        fmap fst <$> readPackageConfig "package.yml" `shouldReturn` Right [
+            "Specified source-dir " ++ show "some-dir" ++ " does not exist"
+          , "Specified source-dir " ++ show "some-exec-dir" ++ " does not exist"
+          , "Specified source-dir " ++ show "some-lib-dir" ++ " does not exist"
+          , "Specified source-dir " ++ show "some-test-dir" ++ " does not exist"
+          ]
+
+    context "when package.yml can not be parsed" $ do
       it "returns an error" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           foo: bar
           foo baz
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Left "package.yaml:3:10: could not find expected ':' while scanning a simple key"
+        readPackageConfig "package.yml" `shouldReturn` Left "package.yml:3:10: could not find expected ':' while scanning a simple key"
 
-    context "when package.yaml is invalid" $ do
+    context "when package.yml is invalid" $ do
       it "returns an error" $ do
-        writeFile "package.yaml" [i|
+        writeFile "package.yml" [i|
           executables:
             foo:
               ain: driver/Main.hs
           |]
-        readPackageConfig "package.yaml" `shouldReturn` Left "package.yaml: The key \"main\" was not found"
+        readPackageConfig "package.yml" `shouldReturn` Left "package.yml: The key \"main\" was not found"
+
+    context "when package.yml does not exist" $ do
+      it "returns an error" $
+        readPackageConfig "package.yml" `shouldReturn` Left "package.yml: Yaml file not found: package.yml"
