diff --git a/peyotls-codec.cabal b/peyotls-codec.cabal
--- a/peyotls-codec.cabal
+++ b/peyotls-codec.cabal
@@ -2,7 +2,7 @@
 cabal-version:	>= 1.8
 
 name:		peyotls-codec
-version:	0.3.0.0
+version:	0.3.1.0
 stability:	Experimental
 author:		Yoshikuni Jujo <PAF01143@nifty.ne.jp>
 maintainer:	Yoshikuni Jujo <PAF01143@nifty.ne.jp>
@@ -22,12 +22,12 @@
 source-repository	this
     type:	git
     location:	git://github.com/YoshikuniJujo/peyotls.git
-    tag:	peyotls-0.1.6.9
+    tag:	peyotls-codec-0.3.1.0
 
 library
     hs-source-dirs:	src
     exposed-modules:
-            Network.PeyoTLS.Codec
+            Network.PeyoTLS.Codec, Network.PeyoTLS.Codec.Alert
     other-modules:
             Network.PeyoTLS.Codec.ContentTypes
             Network.PeyoTLS.Codec.Hello, Network.PeyoTLS.Codec.Extension,
@@ -35,7 +35,7 @@
             Network.PeyoTLS.Codec.HSAlg
             Network.PeyoTLS.CipherSuite
     build-depends:
-        base == 4.*, word24 == 1.0.*, bytestring == 0.10.*,
+        base == 4.*, word24 == 1.0.*, bytestring == 0.10.*, monads-tf == 0.1.*,
         asn1-encoding == 0.9.*, asn1-types == 0.3.*,
         x509 == 1.5.*, x509-store == 1.5.*,
         crypto-pubkey == 0.2.*, crypto-pubkey-types == 0.4.*,
diff --git a/src/Network/PeyoTLS/Codec/Alert.hs b/src/Network/PeyoTLS/Codec/Alert.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/PeyoTLS/Codec/Alert.hs
@@ -0,0 +1,131 @@
+{-# LANGUAGE PackageImports, OverloadedStrings #-}
+
+module Network.PeyoTLS.Codec.Alert (Alert(..), AlertLevel(..), AlertDesc(..)) where
+
+import Control.Applicative
+import "monads-tf" Control.Monad.Error.Class (Error(..))
+import Data.Word (Word8)
+import qualified Data.ByteString as BS
+import qualified Codec.Bytable.BigEndian as B
+
+modNm :: String
+modNm = "Network.PeyoTLS.Codec.Alert"
+
+-- | RFC 5246 7.2. Alert Protocol
+--
+-- @
+-- struct {
+-- 	AlertLevel level;
+-- 	AlertDescription description;
+-- } Alert;
+-- @
+
+data Alert
+	= Alert AlertLevel AlertDesc String
+	| ExternalAlert String
+	| NotDetected String deriving Show
+
+instance B.Bytable Alert where
+	encode (Alert al ad _) = B.encode al `BS.append` B.encode ad
+	encode _ = error "Alert.encode"
+	decode alad = let (al, ad) = BS.splitAt 1 alad in
+		Alert <$> B.decode al <*> B.decode ad <*> return ""
+
+-- | RFC 5246 7.2. Alert Protocol
+--
+-- @
+-- enum { warning(1), fatal(2), (255) } AlertLevel;
+-- @
+
+data AlertLevel = ALWarning | ALFtl | ALRaw Word8 deriving Show
+
+instance B.Bytable AlertLevel where
+	encode ALWarning = "\x01"
+	encode ALFtl = "\x02"
+	encode (ALRaw w) = BS.pack [w]
+	decode bs = case BS.unpack bs of
+		[al] -> Right $ case al of
+			1 -> ALWarning; 2 -> ALFtl; _ -> ALRaw al
+		_ -> Left $ modNm ++ ": AlertLevel.decode"
+
+-- | RFC 5246 7.2. Alert Protocol
+--
+-- @
+-- enum {
+-- 	close_notify(0),
+-- 	unexpected_message(10),
+-- 	bad_record_mac(20),
+-- 	decryption_failed_RESERVED(21),
+-- 	record_overflow(22),
+-- 	decompression_failure(30),
+-- 	handshake_failure(40),
+-- 	no_certificate_RESERVED(41),
+-- 	bad_certificate(42),
+-- 	unsupported_certificate(43),
+-- 	certificate_revoked(44),
+-- 	certificate_expired(45),
+-- 	certificate_unknown(46),
+-- 	illegal_parameter(47),
+-- 	unknown_ca(48),
+-- 	access_denied(49),
+-- 	decode_error(50),
+-- 	decrypt_error(51),
+--	export_restriction_RESERVED(60),
+--	protocol_version(70),
+--	insufficient_security(71),
+--	internal_error(80),
+--	user_canceled(90),
+--	no_renegotiation(100),
+--	unsupported_extension(110),
+--	(255)
+-- } AlertDescription;
+-- @
+
+data AlertDesc
+	= ADCloseNotify | ADUnexMsg   | ADBadRecMac  | ADRecOverflow | ADDecFail
+	| ADHsFailure   | ADUnsCert   | ADCertEx     | ADCertUnk     | ADIllParam
+	| ADUnkCa       | ADDecodeErr | ADDecryptErr | ADProtoVer    | ADInsSec
+	| ADInternalErr | ADUnk       | ADRaw Word8
+	deriving Show
+
+instance B.Bytable AlertDesc where
+	encode ADCloseNotify = "\0"
+	encode ADUnexMsg = "\10"
+	encode ADBadRecMac = "\20"
+	encode ADRecOverflow = "\22"
+	encode ADDecFail = "\30"
+	encode ADHsFailure = "\40"
+	encode ADUnsCert = "\43"
+	encode ADCertEx = "\45"
+	encode ADCertUnk = "\46"
+	encode ADIllParam = "\47"
+	encode ADUnkCa = "\48"
+	encode ADDecodeErr = "\50"
+	encode ADDecryptErr = "\51"
+	encode ADProtoVer = "\70"
+	encode ADInsSec = "\71"
+	encode ADInternalErr = "\80"
+	encode ADUnk = error $ modNm ++ ": AlertDesc,encode"
+	encode (ADRaw w) = BS.pack [w]
+	decode bs = case BS.unpack bs of
+		[ad] -> Right $ case ad of
+			0 -> ADCloseNotify
+			10 -> ADUnexMsg
+			20 -> ADBadRecMac
+			22 -> ADRecOverflow
+			30 -> ADDecFail
+			40 -> ADHsFailure
+			43 -> ADUnsCert
+			45 -> ADCertEx
+			46 -> ADCertUnk
+			47 -> ADIllParam
+			48 -> ADUnkCa
+			50 -> ADDecodeErr
+			51 -> ADDecryptErr
+			70 -> ADProtoVer
+			71 -> ADInsSec
+			80 -> ADInternalErr
+			w -> ADRaw w
+		_ -> Left $ modNm ++ ": AlertDesc.decode"
+
+instance Error Alert where strMsg = NotDetected
