diff --git a/Network/DNS/Decode.hs b/Network/DNS/Decode.hs
--- a/Network/DNS/Decode.hs
+++ b/Network/DNS/Decode.hs
@@ -19,9 +19,11 @@
 import Data.Conduit.Network (sourceSocket)
 import Data.IP (IP(..), toIPv4, toIPv6b)
 import Data.Typeable (Typeable)
+import Data.Word (Word16)
 import Network (Socket)
 import Network.DNS.Internal
 import Network.DNS.StateBinary
+import qualified Safe
 
 #if __GLASGOW_HASKELL__ < 709
 import Control.Applicative
@@ -81,22 +83,28 @@
 ----------------------------------------------------------------
 
 decodeFlags :: SGet DNSFlags
-decodeFlags = toFlags <$> get16
+decodeFlags = do
+    word <- get16
+    maybe (fail "Unsupported flags") pure (toFlags word)
   where
-    toFlags flgs = DNSFlags (getQorR flgs)
-                            (getOpcode flgs)
-                            (getAuthAnswer flgs)
-                            (getTrunCation flgs)
-                            (getRecDesired flgs)
-                            (getRecAvailable flgs)
-                            (getRcode flgs)
+    toFlags :: Word16 -> Maybe DNSFlags
+    toFlags flgs = do
+      opcode_ <- getOpcode flgs
+      rcode_ <- getRcode flgs
+      return $ DNSFlags (getQorR flgs)
+                        opcode_
+                        (getAuthAnswer flgs)
+                        (getTrunCation flgs)
+                        (getRecDesired flgs)
+                        (getRecAvailable flgs)
+                        rcode_
     getQorR w = if testBit w 15 then QR_Response else QR_Query
-    getOpcode w = toEnum $ fromIntegral $ shiftR w 11 .&. 0x0f
+    getOpcode w = Safe.toEnumMay (fromIntegral (shiftR w 11 .&. 0x0f))
     getAuthAnswer w = testBit w 10
     getTrunCation w = testBit w 9
     getRecDesired w = testBit w 8
     getRecAvailable w = testBit w 7
-    getRcode w = toEnum $ fromIntegral $ w .&. 0x0f
+    getRcode w = Safe.toEnumMay (fromIntegral (w .&. 0x0f))
 
 ----------------------------------------------------------------
 
diff --git a/Network/DNS/Internal.hs b/Network/DNS/Internal.hs
--- a/Network/DNS/Internal.hs
+++ b/Network/DNS/Internal.hs
@@ -143,9 +143,21 @@
 
 data QorR = QR_Query | QR_Response deriving (Eq, Show)
 
-data OPCODE = OP_STD | OP_INV | OP_SSR deriving (Eq, Show, Enum)
+data OPCODE
+  = OP_STD
+  | OP_INV
+  | OP_SSR
+  deriving (Eq, Show, Enum, Bounded)
 
-data RCODE = NoErr | FormatErr | ServFail | NameErr | NotImpl | Refused | BadOpt deriving (Eq, Show, Enum)
+data RCODE
+  = NoErr
+  | FormatErr
+  | ServFail
+  | NameErr
+  | NotImpl
+  | Refused
+  | BadOpt
+  deriving (Eq, Show, Enum, Bounded)
 
 ----------------------------------------------------------------
 
diff --git a/dns.cabal b/dns.cabal
--- a/dns.cabal
+++ b/dns.cabal
@@ -1,5 +1,5 @@
 Name:                   dns
-Version:                2.0.2
+Version:                2.0.3
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -39,6 +39,7 @@
                       , network >= 2.3
                       , random
                       , resourcet
+                      , safe == 0.3.*
   else
     Build-Depends:      base >= 4 && < 5
                       , attoparsec
@@ -54,6 +55,7 @@
                       , network-bytestring
                       , random
                       , resourcet
+                      , safe == 0.3.*
 
 Test-Suite network
   Type:                 exitcode-stdio-1.0
@@ -90,6 +92,7 @@
                       , network >= 2.3
                       , random
                       , resourcet
+                      , safe == 0.3.*
                       , word8
 
 Test-Suite doctest
