diff --git a/MeshLib/Elements/Element.h b/MeshLib/Elements/Element.h
index 1f8fc4cb52db0558923dcc3d601d3545aef5d1d7..f894809fcad9966acce509fa65de865fa8e6cc1b 100644
--- a/MeshLib/Elements/Element.h
+++ b/MeshLib/Elements/Element.h
@@ -133,11 +133,14 @@ public:
 	 */
 	unsigned getValue() const { return _value; }
 
+	/// Returns true if these two indeces form an edge and false otherwise
+	virtual bool isEdge(unsigned i, unsigned j) const = 0;
+
 	/**
-	 * Tests if the element is geometrically valid, i.e. convex with volume > 0.
+	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if length/area/volume == 0 should be checked
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const = 0;
+	virtual ElementErrorCode isValid() const = 0;
 
 	/**
 	 * Set the index value for external information.
@@ -151,9 +154,6 @@ public:
 	/// Destructor
 	virtual ~Element();
 
-	/// Returns true if these two indeces form an edge and false otherwise
-	virtual bool isEdge(unsigned i, unsigned j) const = 0;
-
 	/**
 	 * Method clone is a pure virtual method in the abstract base class Element.
 	 * It has to be implemented in the derived classes (for instance in class Hex).
diff --git a/MeshLib/Elements/TemplateHex.h b/MeshLib/Elements/TemplateHex.h
index bd3b6976f622335deed19b0b55cdb81dbc27c1a7..1f2704ad2b03d81c3c8fdf606161432d5c44a83f 100644
--- a/MeshLib/Elements/TemplateHex.h
+++ b/MeshLib/Elements/TemplateHex.h
@@ -102,7 +102,7 @@ public:
 	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if volume == 0 should be checked
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 	/**
 	 * Method clone is inherited from class Element. It makes a deep copy of the Hex instance.
diff --git a/MeshLib/Elements/TemplateHex.tpp b/MeshLib/Elements/TemplateHex.tpp
index 508511f2d35d833e7d938774d7238ef81796dfbb..1a2cec245237f01a4f0c2b010f2859867b2f460a 100644
--- a/MeshLib/Elements/TemplateHex.tpp
+++ b/MeshLib/Elements/TemplateHex.tpp
@@ -156,20 +156,19 @@ unsigned TemplateHex<NNODES,CELLHEXTYPE>::identifyFace(Node* nodes[3]) const
 }
 
 template <unsigned NNODES, CellType CELLHEXTYPE>
-bool TemplateHex<NNODES,CELLHEXTYPE>::isValid(bool check_zero_volume) const
+ElementErrorCode TemplateHex<NNODES,CELLHEXTYPE>::isValid() const
 {
-	if (check_zero_volume && this->_volume <= std::numeric_limits<double>::epsilon())
-		return false;
+	ElementErrorCode error_code(ElementErrorCode::NoError);
+	if (this->_volume < std::numeric_limits<double>::epsilon())
+		error_code = error_code | ElementErrorCode::ZeroVolume;
 
 	for (unsigned i=0; i<6; ++i)
 	{
 		const MeshLib::Quad* quad (dynamic_cast<const MeshLib::Quad*>(this->getFace(i)));
-		const bool quad_is_valid (quad->isValid());
+		error_code = error_code | quad->isValid();
 		delete quad;
-		if (!quad_is_valid)
-			return false;
 	}
-	return true;
+	return error_code;
 }
 
 template <unsigned NNODES, CellType CELLHEXTYPE>
diff --git a/MeshLib/Elements/TemplateLine.h b/MeshLib/Elements/TemplateLine.h
index e570d6b7061eaf618202066f084ed39a0a335761..c21d1c860a785910a8f807cb9953f24a411cdcad 100644
--- a/MeshLib/Elements/TemplateLine.h
+++ b/MeshLib/Elements/TemplateLine.h
@@ -75,8 +75,9 @@ public:
 	/**
 	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if area == 0 should be checked
+	 * @return error code (0 = okay, 1 = zero volume)
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 	/**
 	 * Method clone is inherited from class Element. It makes a deep copy of the TemplateLine instance.
diff --git a/MeshLib/Elements/TemplateLine.tpp b/MeshLib/Elements/TemplateLine.tpp
index c2b2031e2cd6039f5e0c26923e80534e7b94e2db..1ebf309b1a41b2e6e294458ca485042b3f393783 100644
--- a/MeshLib/Elements/TemplateLine.tpp
+++ b/MeshLib/Elements/TemplateLine.tpp
@@ -48,11 +48,12 @@ TemplateLine<NNODES,CELLLINETYPE>::~TemplateLine()
 {}
 
 template <unsigned NNODES, CellType CELLLINETYPE>
-bool TemplateLine<NNODES,CELLLINETYPE>::isValid(bool check_zero_volume) const
+ElementErrorCode TemplateLine<NNODES,CELLLINETYPE>::isValid() const
 { 
-	if (check_zero_volume)
-		return (this->_length > std::numeric_limits<double>::epsilon());
-	return true;
+	ElementErrorCode error_code (ElementErrorCode::NoError);
+	if (this->_length < std::numeric_limits<double>::epsilon())
+		error_code =  error_code | ElementErrorCode::ZeroVolume;
+	return error_code;
 }
 
 } // namespace MeshLib
diff --git a/MeshLib/Elements/TemplatePrism.h b/MeshLib/Elements/TemplatePrism.h
index 3dd0b175586f17897d9352c443f5994004cfac38..f93fa301a0c8c728999f0e9dce9ada0143be6fe1 100644
--- a/MeshLib/Elements/TemplatePrism.h
+++ b/MeshLib/Elements/TemplatePrism.h
@@ -100,7 +100,7 @@ public:
 	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if volume == 0 should be checked
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 	/**
 	 * Method clone is inherited from class Element. It makes a deep copy of the
diff --git a/MeshLib/Elements/TemplatePrism.tpp b/MeshLib/Elements/TemplatePrism.tpp
index 9d9f4fed744ee0e08eb2dc5e946d384f4195735a..85ee56cfbfc448f968e344c437e784dfb34d9938 100644
--- a/MeshLib/Elements/TemplatePrism.tpp
+++ b/MeshLib/Elements/TemplatePrism.tpp
@@ -165,20 +165,22 @@ unsigned TemplatePrism<NNODES,CELLPRISMTYPE>::identifyFace(Node* nodes[3]) const
 }
 
 template <unsigned NNODES, CellType CELLPRISMTYPE>
-bool TemplatePrism<NNODES,CELLPRISMTYPE>::isValid(bool check_zero_volume) const
+ElementErrorCode TemplatePrism<NNODES,CELLPRISMTYPE>::isValid() const
 {
-	if (check_zero_volume && this->_volume <= std::numeric_limits<double>::epsilon())
-		return false;
+	ElementErrorCode error_code(ElementErrorCode::NoError);
+	if (this->_volume < std::numeric_limits<double>::epsilon())
+		error_code = error_code | ElementErrorCode::ZeroVolume;
 
 	for (unsigned i=1; i<4; ++i)
 	{
 		const MeshLib::Quad* quad (dynamic_cast<const MeshLib::Quad*>(this->getFace(i)));
-		const bool quad_is_valid (quad->isValid());
+		if (quad)
+			error_code = error_code | quad->isValid();
+		else 
+			error_code = error_code | ElementErrorCode::NodeOrder;
 		delete quad;
-		if (!quad_is_valid)
-			return false;
 	}
-	return true;
+	return error_code;
 }
 
 template <unsigned NNODES, CellType CELLPRISMTYPE>
diff --git a/MeshLib/Elements/TemplatePyramid.h b/MeshLib/Elements/TemplatePyramid.h
index f687476419b170a357bc34da80f20b07272f3b37..bc4db2f0bbe035a7fd42fe6d9c4cd2e861991b75 100644
--- a/MeshLib/Elements/TemplatePyramid.h
+++ b/MeshLib/Elements/TemplatePyramid.h
@@ -98,7 +98,7 @@ public:
 	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if volume == 0 should be checked
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 	/**
 	 * Method clone is inherited from class Element. It makes a deep copy of the
diff --git a/MeshLib/Elements/TemplatePyramid.tpp b/MeshLib/Elements/TemplatePyramid.tpp
index fe3e01b1a9d97fc291c5b6e56fc612149c83f3d0..d572550b265026c50dcea857f5139d057a2906eb 100644
--- a/MeshLib/Elements/TemplatePyramid.tpp
+++ b/MeshLib/Elements/TemplatePyramid.tpp
@@ -167,15 +167,20 @@ unsigned TemplatePyramid<NNODES,CELLPYRAMIDTYPE>::identifyFace(Node* nodes[3]) c
 }
 
 template <unsigned NNODES, CellType CELLPYRAMIDTYPE>
-bool TemplatePyramid<NNODES,CELLPYRAMIDTYPE>::isValid(bool check_zero_volume) const
+ElementErrorCode TemplatePyramid<NNODES,CELLPYRAMIDTYPE>::isValid() const
 {
-	if (check_zero_volume && this->_volume <= std::numeric_limits<double>::epsilon())
-		return false;
+	ElementErrorCode error_code(ElementErrorCode::NoError);
+	if (this->_volume < std::numeric_limits<double>::epsilon())
+		error_code = error_code | ElementErrorCode::ZeroVolume;
 
 	const MeshLib::Quad* base (dynamic_cast<const MeshLib::Quad*>(this->getFace(4)));
-	const bool base_is_valid (base->isValid());
+	if (base)
+		error_code = error_code | base->isValid();
+	else
+		error_code = error_code | ElementErrorCode::NodeOrder;
 	delete base;
-	return base_is_valid;
+
+	return error_code;
 }
 
 
diff --git a/MeshLib/Elements/TemplateQuad.h b/MeshLib/Elements/TemplateQuad.h
index b30fa029f50c10060eb5a84c082a4e755dcb048c..9ae3f9120dda031fa8f65d416dc38d71e9c40afc 100644
--- a/MeshLib/Elements/TemplateQuad.h
+++ b/MeshLib/Elements/TemplateQuad.h
@@ -101,7 +101,7 @@ public:
 	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if area == 0 should be checked
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 	/**
 	 * Method clone is inherited from class Element. It makes a deep copy of the TemplateQuad instance.
diff --git a/MeshLib/Elements/TemplateQuad.tpp b/MeshLib/Elements/TemplateQuad.tpp
index fbf45baaa6de30ddeac3c4d0bb338fe5477fc896..49fb74f5d8dddbf36920c5f5499368e779a89a86 100644
--- a/MeshLib/Elements/TemplateQuad.tpp
+++ b/MeshLib/Elements/TemplateQuad.tpp
@@ -120,19 +120,19 @@ unsigned TemplateQuad<NNODES,CELLQUADTYPE>::identifyFace(Node* nodes[3]) const
 }
 
 template <unsigned NNODES, CellType CELLQUADTYPE>
-bool TemplateQuad<NNODES,CELLQUADTYPE>::isValid(bool check_zero_volume) const
+ElementErrorCode TemplateQuad<NNODES,CELLQUADTYPE>::isValid() const
 {
-	if (check_zero_volume && this->_area <= std::numeric_limits<double>::epsilon())
-		return false;
+	ElementErrorCode error_code(ElementErrorCode::NoError);
+	if (this->_area < std::numeric_limits<double>::epsilon())
+		error_code = error_code | ElementErrorCode::ZeroVolume;
 
-	if (GeoLib::pointsOnAPlane(*_nodes[0], *_nodes[1], *_nodes[2], *_nodes[3]))
-	{
-		// check if quad is convex
-		if (GeoLib::dividedByPlane(*_nodes[0], *_nodes[2], *_nodes[1], *_nodes[3]) &&
-			GeoLib::dividedByPlane(*_nodes[1], *_nodes[3], *_nodes[0], *_nodes[2]))
-			return true;
-	}
-	return false;
+	if (!GeoLib::pointsOnAPlane(*_nodes[0], *_nodes[1], *_nodes[2], *_nodes[3]))
+		error_code = error_code | ElementErrorCode::NonCoplanar;
+
+	if (!(GeoLib::dividedByPlane(*_nodes[0], *_nodes[2], *_nodes[1], *_nodes[3]) &&
+		  GeoLib::dividedByPlane(*_nodes[1], *_nodes[3], *_nodes[0], *_nodes[2])))
+		  error_code = error_code | ElementErrorCode::NonConvex;
+	return error_code;
 }
 
 template <unsigned NNODES, CellType CELLQUADTYPE>
diff --git a/MeshLib/Elements/TemplateTet.h b/MeshLib/Elements/TemplateTet.h
index cadd972d88cb5db58eedd9855278b82071e8f4a4..f5030d0dd8b2020a5cea7ff55cafbfaef66b95ce 100644
--- a/MeshLib/Elements/TemplateTet.h
+++ b/MeshLib/Elements/TemplateTet.h
@@ -97,7 +97,7 @@ public:
 	 * Tests if the element is geometrically valid.
 	 * @param check_zero_volume indicates if volume == 0 should be checked
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 	/**
 	 * Method clone is inherited from class Element. It makes a deep copy of the TemplateTet instance.
diff --git a/MeshLib/Elements/TemplateTet.tpp b/MeshLib/Elements/TemplateTet.tpp
index c2497161cdf6d520e34adaff37f3dc4844f248f6..c83c65cddbcc5bc166c15b050fd98054e73e23f7 100644
--- a/MeshLib/Elements/TemplateTet.tpp
+++ b/MeshLib/Elements/TemplateTet.tpp
@@ -145,11 +145,12 @@ unsigned TemplateTet<NNODES,CELLTETTYPE>::identifyFace(Node* nodes[3]) const
 }
 
 template <unsigned NNODES, CellType CELLTETTYPE>
-bool TemplateTet<NNODES,CELLTETTYPE>::isValid(bool check_zero_volume) const
+ElementErrorCode TemplateTet<NNODES,CELLTETTYPE>::isValid() const
 { 
-	if (check_zero_volume)
-		return (this->_volume > std::numeric_limits<double>::epsilon()); 
-	return true;
+	ElementErrorCode error_code(ElementErrorCode::NoError);
+	if (this->_volume < std::numeric_limits<double>::epsilon())
+		error_code = error_code | ElementErrorCode::ZeroVolume;
+	return error_code;
 }
 
 template <unsigned NNODES, CellType CELLTETTYPE>
diff --git a/MeshLib/Elements/TemplateTri.h b/MeshLib/Elements/TemplateTri.h
index f352d14486945441f2da3962059d6df7471ab42e..9cd9fc4c60b458d03293edef84750354eaf8cca7 100644
--- a/MeshLib/Elements/TemplateTri.h
+++ b/MeshLib/Elements/TemplateTri.h
@@ -97,8 +97,9 @@ public:
 	/**
 	 * Tests if the element is geometrically valid
 	 * @param check_zero_volume indicates if area == 0 should be checked
+	 * @return error code (0 = okay, 1 = zero volume)
 	 */
-	virtual bool isValid(bool check_zero_volume = true) const;
+	virtual ElementErrorCode isValid() const;
 
 
 	/**
diff --git a/MeshLib/Elements/TemplateTri.tpp b/MeshLib/Elements/TemplateTri.tpp
index 3d386395e879536c4a2af1a769e9651234ced408..ee7ecba68f600d106cd6582db4f70259a0a938e2 100644
--- a/MeshLib/Elements/TemplateTri.tpp
+++ b/MeshLib/Elements/TemplateTri.tpp
@@ -81,11 +81,12 @@ bool TemplateTri<NNODES,CELLTRITYPE>::isPntInside(GeoLib::Point const& pnt, doub
 }
 
 template <unsigned NNODES, CellType CELLTRITYPE>
-bool TemplateTri<NNODES,CELLTRITYPE>::isValid(bool check_zero_volume) const 
+ElementErrorCode TemplateTri<NNODES,CELLTRITYPE>::isValid() const 
 { 
-	if (check_zero_volume)
-		return (this->_area > std::numeric_limits<double>::epsilon()); 
-	return true;
+	ElementErrorCode error_code (ElementErrorCode::NoError);
+	if (this->_area < std::numeric_limits<double>::epsilon())
+		error_code = error_code | ElementErrorCode::ZeroVolume;
+	return error_code;
 }
 
 
diff --git a/MeshLib/MeshEnums.h b/MeshLib/MeshEnums.h
index 224126337463badbc81cde5e453618f92a24e52f..28d2b83c680892181f914224c15133a090db5095 100644
--- a/MeshLib/MeshEnums.h
+++ b/MeshLib/MeshEnums.h
@@ -68,6 +68,15 @@ enum class MeshQualityType
 	EQUIANGLESKEW
 };
 
+enum ElementErrorCode 
+{
+	NoError     = 0x00,
+	ZeroVolume  = 0x01,
+	NonCoplanar = 0x02,
+	NonConvex   = 0x04,
+	NodeOrder   = 0x08
+};
+
 /// Given a MeshElemType this returns the appropriate string.
 const std::string MeshElemType2String(const MeshElemType t);
 
@@ -76,4 +85,8 @@ MeshElemType String2MeshElemType(const std::string &s);
 
 const std::string MeshQualityType2String(const MeshQualityType t);
 
+inline ElementErrorCode operator|(ElementErrorCode a, ElementErrorCode b)
+{return static_cast<ElementErrorCode>(static_cast<int>(a) | static_cast<int>(b));}
+
+
 #endif //MESHENUMS_H
diff --git a/MeshLib/MeshQuality/MeshQualityController.h b/MeshLib/MeshQuality/MeshQualityController.h
index 2a3d486e6bd18e211873292b17e18878360639a8..831624193e59892ff0f45bd3da65e626da1fde17 100644
--- a/MeshLib/MeshQuality/MeshQualityController.h
+++ b/MeshLib/MeshQuality/MeshQualityController.h
@@ -21,7 +21,7 @@ namespace MeshLib {
 	class Mesh;
 
 /**
- * \brief A set of methods for manipulating mesh element values
+ * \brief A collection of methods for testing mesh quality and correctness
  */
 class MeshQualityController
 {