diff --git a/tscpp.cpp b/tscpp.cpp
index ae0ca42ba41228635e932ffcac1f2893f4c2499b..a058fcb27562127d4ec9c592a460eca207eead3a 100644
--- a/tscpp.cpp
+++ b/tscpp.cpp
@@ -90,7 +90,7 @@ string peekTypeName(const void *buffer, int bufSize)
 {
     const char *buf=reinterpret_cast<const char*>(buffer);
     int nameSize=strnlen(buf,bufSize);
-    if(nameSize>=bufSize) return "<corrupted>";
+    if(nameSize>=bufSize) return "";
     return buf;
 }
 
@@ -117,30 +117,31 @@ void OutputArchive::serializeImpl(const char *name, const void *data, int size)
 
 void InputArchive::unserializeImpl(const char *name, void *data, int size)
 {
-    auto pos=is.tellg();
+    pos=is.tellg();
     int nameSize=strlen(name);
     unique_ptr<char[]> unserializedName(new char[nameSize+1]);
     is.read(unserializedName.get(),nameSize+1);
-    if(is.eof())
-    {
-        is.seekg(pos);
-        throw 1; //FIXME
-    }
+    if(is.eof()) errorImpl("eof");
 
     if(memcmp(unserializedName.get(),name,nameSize+1))
-    {
-        is.seekg(pos);
-        throw 2; //FIXME
-    }
+        errorImpl("wrong type found",true);
 
     //NOTE: we are writing on top of a constructed type without calling its
     //destructor. However, since it is trivially copyable, we at least aren't
     //overwriting pointers to allocated memory.
     is.read(reinterpret_cast<char*>(data),size);
-    if(is.eof())
-    {
+    if(is.eof()) errorImpl("eof");
+}
+
+void InputArchive::errorImpl(const string& errorStr, bool printName)
+{
+    is.seekg(pos);
+    if(printName==false) throw TscppException(errorStr);
+    else {
+        string type;
+        getline(is,type,'\0');
         is.seekg(pos);
-        throw 3; //FIXME
+        throw TscppException(errorStr,type);
     }
 }
 
diff --git a/tscpp.h b/tscpp.h
index d46b3489349e559b5434b1fce67e25989208f080..f3b9d67139fbc25d9cec03d770e86c6fdf6d55be 100644
--- a/tscpp.h
+++ b/tscpp.h
@@ -29,6 +29,7 @@
 
 #include <type_traits>
 #include <functional>
+#include <stdexcept>
 #include <ostream>
 #include <istream>
 #include <cstring>
@@ -174,8 +175,8 @@ int unserializeUnknown(const TypePool& tp, const void *buffer, int bufSize);
  * \endcode
  * \param buffer pointer to buffer where the serialized type is
  * \param bufSize buffer size
- * \return the serialized type name, or "<corrupted>" if the buffer does not
- * contain a type name
+ * \return the serialized type name, or "" if the buffer does not contain a type
+ * name
  */
 std::string peekTypeName(const void *buffer, int bufSize);
 
@@ -249,18 +250,26 @@ public:
      * \internal
      */
     void unserializeImpl(const char *name, void *data, int size);
+    
+    /**
+     * \internal
+     */
+    void errorImpl(const std::string& errorStr, bool printName=false);
 
 private:
     InputArchive(const InputArchive&)=delete;
     InputArchive& operator=(const InputArchive&)=delete;
 
     std::istream& is;
+    std::streampos pos;
 };
 
 /**
  * Unserialize a type
  * \param ia archive where the type has been serialized
  * \param t type to unserialize
+ * \throws TscppException if the type found in the stream is not the one
+ * expected, or if the stream eof is found
  */
 template<typename T>
 InputArchive& operator>>(InputArchive& ia, T& t)
@@ -272,4 +281,45 @@ InputArchive& operator>>(InputArchive& ia, T& t)
     return ia;
 }
 
+/**
+ * Exception class thrown by the input archives
+ */
+class TscppException : public std::runtime_error
+{
+public:
+    /**
+     * \internal
+     */
+    TscppException(const std::string& what) : runtime_error(what) {}
+    
+    /**
+     * \internal
+     */
+    TscppException(const std::string& what, const std::string& t)
+        : runtime_error(what), t(t) {}
+    
+    /**
+     * If the exception is thrown because an unknown/unexpected type has been
+     * found in the input stream, this member function allows to access the
+     * mangled type name.
+     * It is useful to print an error message with the name of the type in the
+     * stream
+     * \code
+     * InputArchive ia(is);
+     * Foo f;
+     * try {
+     *     ia>>f;
+     * } catch(TscppException& ex) {
+     *     if(ex.type().empty()==false)
+     *         cerr<<"While unserializing Foo, "<<demangle(ex.type())<<" was found\n";
+     * }
+     * \endcode
+     * \return the serialized type name, or "" if eof was found
+     */
+    std::string type() const { return t; }
+
+private:
+    std::string t;
+};
+
 } // namespace tscpp