diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index afc801f9a42a50237ca101fac1f4989168ca718c..d14bb65e0a1aa0c98fb6cac6405ef0b9433fc7ef 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -2027,6 +2027,10 @@ class _VerifyErrors(object):
     """
     ltype = kwargs.get(self.ETYPE_FIELD, self.ETYPE_ERROR)
     itype, etxt, _ = ecode
+    # If the error code is in the list of ignored errors, demote the error to a
+    # warning
+    if etxt in self.op.ignore_errors:     # pylint: disable=E1101
+      ltype = self.ETYPE_WARNING
     # first complete the msg
     if args:
       msg = msg % args
@@ -2041,26 +2045,17 @@ class _VerifyErrors(object):
       msg = "%s: %s%s: %s" % (ltype, itype, item, msg)
     # and finally report it via the feedback_fn
     self._feedback_fn("  - %s" % msg) # Mix-in. pylint: disable=E1101
+    # do not mark the operation as failed for WARN cases only
+    if ltype == self.ETYPE_ERROR:
+      self.bad = True
 
-  def _ErrorIf(self, cond, ecode, *args, **kwargs):
+  def _ErrorIf(self, cond, *args, **kwargs):
     """Log an error message if the passed condition is True.
 
     """
-    cond = (bool(cond)
-            or self.op.debug_simulate_errors) # pylint: disable=E1101
-
-    # If the error code is in the list of ignored errors, demote the error to a
-    # warning
-    (_, etxt, _) = ecode
-    if etxt in self.op.ignore_errors:     # pylint: disable=E1101
-      kwargs[self.ETYPE_FIELD] = self.ETYPE_WARNING
-
-    if cond:
-      self._Error(ecode, *args, **kwargs)
-
-    # do not mark the operation as failed for WARN cases only
-    if kwargs.get(self.ETYPE_FIELD, self.ETYPE_ERROR) == self.ETYPE_ERROR:
-      self.bad = self.bad or cond
+    if (bool(cond)
+        or self.op.debug_simulate_errors): # pylint: disable=E1101
+      self._Error(*args, **kwargs)
 
 
 class LUClusterVerify(NoHooksLU):
diff --git a/test/py/ganeti.cmdlib_unittest.py b/test/py/ganeti.cmdlib_unittest.py
index 5df77eb7aebd0df3b50d58117ad021265753bd83..e43b1fb77a56435fd04c659c64fca4012de699c1 100755
--- a/test/py/ganeti.cmdlib_unittest.py
+++ b/test/py/ganeti.cmdlib_unittest.py
@@ -1533,5 +1533,143 @@ class TestCheckOpportunisticLocking(unittest.TestCase):
           cmdlib._CheckOpportunisticLocking(op)
 
 
+class _OpTestVerifyErrors(opcodes.OpCode):
+  OP_PARAMS = [
+    opcodes._PDebugSimulateErrors,
+    opcodes._PErrorCodes,
+    opcodes._PIgnoreErrors,
+    ]
+
+
+class _LuTestVerifyErrors(cmdlib._VerifyErrors):
+  def __init__(self, **kwargs):
+    cmdlib._VerifyErrors.__init__(self)
+    self.op = _OpTestVerifyErrors(**kwargs)
+    self.op.Validate(True)
+    self.msglist = []
+    self._feedback_fn = self.msglist.append
+    self.bad = False
+
+  def DispatchCallError(self, which, *args, **kwargs):
+    if which:
+      self._Error(*args, **kwargs)
+    else:
+      self._ErrorIf(True, *args, **kwargs)
+
+  def CallErrorIf(self, c, *args, **kwargs):
+    self._ErrorIf(c, *args, **kwargs)
+
+
+class TestVerifyErrors(unittest.TestCase):
+  # Fake cluster-verify error code structures; we use two arbitary real error
+  # codes to pass validation of ignore_errors
+  (_, _ERR1ID, _) = constants.CV_ECLUSTERCFG
+  _NODESTR = "node"
+  _NODENAME = "mynode"
+  _ERR1CODE = (_NODESTR, _ERR1ID, "Error one")
+  (_, _ERR2ID, _) = constants.CV_ECLUSTERCERT
+  _INSTSTR = "instance"
+  _INSTNAME = "myinstance"
+  _ERR2CODE = (_INSTSTR, _ERR2ID, "Error two")
+  # Arguments used to call _Error() or _ErrorIf()
+  _ERR1ARGS = (_ERR1CODE, _NODENAME, "Error1 is %s", "an error")
+  _ERR2ARGS = (_ERR2CODE, _INSTNAME, "Error2 has no argument")
+  # Expected error messages
+  _ERR1MSG = _ERR1ARGS[2] % _ERR1ARGS[3]
+  _ERR2MSG = _ERR2ARGS[2]
+
+  def testNoError(self):
+    lu = _LuTestVerifyErrors()
+    lu.CallErrorIf(False, self._ERR1CODE, *self._ERR1ARGS)
+    self.assertFalse(lu.bad)
+    self.assertFalse(lu.msglist)
+
+  def _InitTest(self, **kwargs):
+    self.lu1 = _LuTestVerifyErrors(**kwargs)
+    self.lu2 = _LuTestVerifyErrors(**kwargs)
+
+  def _CallError(self, *args, **kwargs):
+    # Check that _Error() and _ErrorIf() produce the same results
+    self.lu1.DispatchCallError(True, *args, **kwargs)
+    self.lu2.DispatchCallError(False, *args, **kwargs)
+    self.assertEqual(self.lu1.bad, self.lu2.bad)
+    self.assertEqual(self.lu1.msglist, self.lu2.msglist)
+    # Test-specific checks are made on one LU
+    return self.lu1
+
+  def _checkMsgCommon(self, logstr, errmsg, itype, item, warning):
+    self.assertTrue(errmsg in logstr)
+    if warning:
+      self.assertTrue("WARNING" in logstr)
+    else:
+      self.assertTrue("ERROR" in logstr)
+    self.assertTrue(itype in logstr)
+    self.assertTrue(item in logstr)
+
+  def _checkMsg1(self, logstr, warning=False):
+    self._checkMsgCommon(logstr, self._ERR1MSG, self._NODESTR,
+                         self._NODENAME, warning)
+
+  def _checkMsg2(self, logstr, warning=False):
+    self._checkMsgCommon(logstr, self._ERR2MSG, self._INSTSTR,
+                         self._INSTNAME, warning)
+
+  def testPlain(self):
+    self._InitTest()
+    lu = self._CallError(*self._ERR1ARGS)
+    self.assertTrue(lu.bad)
+    self.assertEqual(len(lu.msglist), 1)
+    self._checkMsg1(lu.msglist[0])
+
+  def testMultiple(self):
+    self._InitTest()
+    self._CallError(*self._ERR1ARGS)
+    lu = self._CallError(*self._ERR2ARGS)
+    self.assertTrue(lu.bad)
+    self.assertEqual(len(lu.msglist), 2)
+    self._checkMsg1(lu.msglist[0])
+    self._checkMsg2(lu.msglist[1])
+
+  def testIgnore(self):
+    self._InitTest(ignore_errors=[self._ERR1ID])
+    lu = self._CallError(*self._ERR1ARGS)
+    self.assertFalse(lu.bad)
+    self.assertEqual(len(lu.msglist), 1)
+    self._checkMsg1(lu.msglist[0], warning=True)
+
+  def testWarning(self):
+    self._InitTest()
+    lu = self._CallError(*self._ERR1ARGS,
+                         code=_LuTestVerifyErrors.ETYPE_WARNING)
+    self.assertFalse(lu.bad)
+    self.assertEqual(len(lu.msglist), 1)
+    self._checkMsg1(lu.msglist[0], warning=True)
+
+  def testWarning2(self):
+    self._InitTest()
+    self._CallError(*self._ERR1ARGS)
+    lu = self._CallError(*self._ERR2ARGS,
+                         code=_LuTestVerifyErrors.ETYPE_WARNING)
+    self.assertTrue(lu.bad)
+    self.assertEqual(len(lu.msglist), 2)
+    self._checkMsg1(lu.msglist[0])
+    self._checkMsg2(lu.msglist[1], warning=True)
+
+  def testDebugSimulate(self):
+    lu = _LuTestVerifyErrors(debug_simulate_errors=True)
+    lu.CallErrorIf(False, *self._ERR1ARGS)
+    self.assertTrue(lu.bad)
+    self.assertEqual(len(lu.msglist), 1)
+    self._checkMsg1(lu.msglist[0])
+
+  def testErrCodes(self):
+    self._InitTest(error_codes=True)
+    lu = self._CallError(*self._ERR1ARGS)
+    self.assertTrue(lu.bad)
+    self.assertEqual(len(lu.msglist), 1)
+    self._checkMsg1(lu.msglist[0])
+    self.assertTrue(self._ERR1ID in lu.msglist[0])
+
+
 if __name__ == "__main__":
   testutils.GanetiTestProgram()