diff --git a/ironic_python_agent/errors.py b/ironic_python_agent/errors.py
index 0b46465ff..6058d1918 100644
--- a/ironic_python_agent/errors.py
+++ b/ironic_python_agent/errors.py
@@ -22,10 +22,12 @@ class RESTError(Exception, encoding.Serializable):
     status_code = 500
     serializable_fields = ('type', 'code', 'message', 'details')
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, details=None, *args, **kwargs):
         super(RESTError, self).__init__(*args, **kwargs)
         self.type = self.__class__.__name__
         self.code = self.status_code
+        if details:
+            self.details = details
 
 
 class InvalidContentError(RESTError):
@@ -37,7 +39,7 @@ class InvalidContentError(RESTError):
     status_code = 400
 
     def __init__(self, details):
-        self.details = details
+        super(InvalidContentError, self).__init__(details)
 
 
 class NotFound(RESTError):
@@ -56,8 +58,7 @@ class CommandExecutionError(RESTError):
     message = 'Command execution failed'
 
     def __init__(self, details):
-        super(CommandExecutionError, self).__init__()
-        self.details = details
+        super(CommandExecutionError, self).__init__(details)
 
 
 class InvalidCommandError(InvalidContentError):
@@ -82,7 +83,6 @@ class RequestedObjectNotFoundError(NotFound):
     def __init__(self, type_descr, obj_id):
         details = '{0} with id {1} not found.'.format(type_descr, obj_id)
         super(RequestedObjectNotFoundError, self).__init__(details)
-        self.details = details
 
 
 class IronicAPIError(RESTError):
@@ -92,7 +92,6 @@ class IronicAPIError(RESTError):
 
     def __init__(self, details):
         super(IronicAPIError, self).__init__(details)
-        self.details = details
 
 
 class HeartbeatError(IronicAPIError):
@@ -139,8 +138,8 @@ class ImageDownloadError(RESTError):
     message = 'Error downloading image.'
 
     def __init__(self, image_id):
-        super(ImageDownloadError, self).__init__()
-        self.details = 'Could not download image with id {0}.'.format(image_id)
+        details = 'Could not download image with id {0}.'.format(image_id)
+        super(ImageDownloadError, self).__init__(details)
 
 
 class ImageChecksumError(RESTError):
@@ -149,9 +148,9 @@ class ImageChecksumError(RESTError):
     message = 'Error verifying image checksum.'
 
     def __init__(self, image_id):
-        super(ImageChecksumError, self).__init__()
-        self.details = 'Image with id {0} failed to verify against checksum.'
-        self.details = self.details.format(image_id)
+        details = 'Image with id {0} failed to verify against checksum.'
+        details = details.format(image_id)
+        super(ImageChecksumError, self).__init__(details)
 
 
 class ImageWriteError(RESTError):
@@ -160,10 +159,10 @@ class ImageWriteError(RESTError):
     message = 'Error writing image to device.'
 
     def __init__(self, device, exit_code, stdout, stderr):
-        super(ImageWriteError, self).__init__()
-        self.details = ('Writing image to device {0} failed with exit code '
-                        '{1}. stdout: {2}. stderr: {3}')
-        self.details = self.details.format(device, exit_code, stdout, stderr)
+        details = ('Writing image to device {0} failed with exit code '
+                   '{1}. stdout: {2}. stderr: {3}')
+        details = details.format(device, exit_code, stdout, stderr)
+        super(ImageWriteError, self).__init__(details)
 
 
 class ConfigDriveTooLargeError(RESTError):
@@ -174,7 +173,6 @@ class ConfigDriveTooLargeError(RESTError):
         details = ('Configdrive at {0} has size {1}, which is larger than '
                    'the intended partition.').format(filename, filesize)
         super(ConfigDriveTooLargeError, self).__init__(details)
-        self.details = details
 
 
 class ConfigDriveWriteError(RESTError):
@@ -189,7 +187,6 @@ class ConfigDriveWriteError(RESTError):
                    '{1}. stdout: {2}. stderr: {3}.')
         details = details.format(device, exit_code, stdout, stderr)
         super(ConfigDriveWriteError, self).__init__(details)
-        self.details = details
 
 
 class SystemRebootError(RESTError):
@@ -198,10 +195,10 @@ class SystemRebootError(RESTError):
     message = 'Error rebooting system.'
 
     def __init__(self, exit_code, stdout, stderr):
-        super(SystemRebootError, self).__init__()
-        self.details = ('Reboot script failed with exit code {0}. stdout: '
-                        '{1}. stderr: {2}.')
-        self.details = self.details.format(exit_code, stdout, stderr)
+        details = ('Reboot script failed with exit code {0}. stdout: '
+                   '{1}. stderr: {2}.')
+        details = details.format(exit_code, stdout, stderr)
+        super(SystemRebootError, self).__init__(details)
 
 
 class BlockDeviceEraseError(RESTError):
@@ -211,7 +208,6 @@ class BlockDeviceEraseError(RESTError):
 
     def __init__(self, details):
         super(BlockDeviceEraseError, self).__init__(details)
-        self.details = details
 
 
 class BlockDeviceError(RESTError):
@@ -220,7 +216,6 @@ class BlockDeviceError(RESTError):
 
     def __init__(self, details):
         super(BlockDeviceError, self).__init__(details)
-        self.details = details
 
 
 class VirtualMediaBootError(RESTError):
@@ -231,7 +226,6 @@ class VirtualMediaBootError(RESTError):
 
     def __init__(self, details):
         super(VirtualMediaBootError, self).__init__(details)
-        self.details = details
 
 
 class ExtensionError(Exception):
@@ -267,8 +261,8 @@ class HardwareManagerMethodNotFound(RESTError):
     message = msg + '.'
 
     def __init__(self, method):
-        self.details = (self.msg + ': "{0}".').format(method)
-        super(HardwareManagerMethodNotFound, self).__init__(self.details)
+        details = (self.msg + ': "{0}".').format(method)
+        super(HardwareManagerMethodNotFound, self).__init__(details)
 
 
 class IncompatibleHardwareMethodError(RESTError):
@@ -280,7 +274,7 @@ class IncompatibleHardwareMethodError(RESTError):
 
     def __init__(self, details=None):
         if details is not None:
-            self.details = details
+            details = details
         else:
-            self.details = self.message
-        super(IncompatibleHardwareMethodError, self).__init__(self.details)
+            details = self.message
+        super(IncompatibleHardwareMethodError, self).__init__(details)
diff --git a/ironic_python_agent/tests/errors.py b/ironic_python_agent/tests/errors.py
new file mode 100644
index 000000000..cc0c0da37
--- /dev/null
+++ b/ironic_python_agent/tests/errors.py
@@ -0,0 +1,118 @@
+#    Copyright (C) 2015 Yahoo! Inc. All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslotest import base as test_base
+
+from ironic_python_agent import errors
+
+DETAILS = 'details'
+SAME_CL_DETAILS = 'same_as_class_details'
+DIFF_CL_DETAILS = 'different_from_class_details'
+SAME_CL_MSG = 'same_as_class_message'
+SAME_DETAILS = 'same_as_DETAILS'
+
+
+class TestErrors(test_base.BaseTestCase):
+
+    def test_RESTError(self):
+        e = errors.RESTError()
+        d = e.serialize()
+
+        self.assertEqual("RESTError", e.type)
+        self.assertEqual(errors.RESTError.status_code, e.code)
+        self.assertEqual(errors.RESTError.message, e.message)
+        self.assertEqual(errors.RESTError.details, e.details)
+
+        self.assertEqual("RESTError", d['type'])
+        self.assertEqual(errors.RESTError.status_code, d['code'])
+        self.assertEqual(errors.RESTError.message, d['message'])
+        self.assertEqual(errors.RESTError.details, d['details'])
+
+    def test_RESTError_details(self):
+        e = errors.RESTError(DETAILS)
+        self.assertEqual("RESTError", e.type)
+        self.assertEqual(500, e.code)
+        self.assertEqual(errors.RESTError.message, e.message)
+        self.assertEqual(DETAILS, e.details)
+
+    def _test_class(self, obj, check_details):
+        """Test that the object is created correctly
+
+        :param obj: object to be tested
+        :param check_details: how to check the object's details value.
+                             One of SAME_CL_DETAILS, DIFF_CL_DETAILS,
+                             SAME_CL_MSG, SAME_DETAILS
+
+        """
+        obj_info = "object info = %s" % obj.__dict__
+        cls = obj.__class__
+        d = obj.serialize()
+
+        self.assertEqual(cls.__name__, obj.type, obj_info)
+        self.assertEqual(cls.status_code, obj.code, obj_info)
+        self.assertEqual(cls.message, obj.message, obj_info)
+
+        self.assertEqual(cls.__name__, d['type'], obj_info)
+        self.assertEqual(cls.status_code, d['code'], obj_info)
+        self.assertEqual(cls.message, d['message'], obj_info)
+        self.assertEqual(obj.details, d['details'], obj_info)
+
+        if check_details == SAME_CL_DETAILS:
+            self.assertEqual(cls.details, obj.details, obj_info)
+        elif check_details == DIFF_CL_DETAILS:
+            self.assertNotEqual(cls.details, obj.details, obj_info)
+        elif check_details == SAME_CL_MSG:
+            self.assertEqual(cls.message, obj.details, obj_info)
+        elif check_details == SAME_DETAILS:
+            self.assertEqual(DETAILS, obj.details, obj_info)
+        else:
+            self.fail("unexpected value for check_details: %(chk)s, %(info)s" %
+                      {'info': obj_info, 'chk': check_details})
+
+    def test_error_classes(self):
+        cases = [(errors.InvalidContentError(DETAILS), SAME_DETAILS),
+                 (errors.NotFound(), SAME_CL_DETAILS),
+                 (errors.CommandExecutionError(DETAILS), SAME_DETAILS),
+                 (errors.InvalidCommandError(DETAILS), SAME_DETAILS),
+                 (errors.InvalidCommandParamsError(DETAILS), SAME_DETAILS),
+                 (errors.RequestedObjectNotFoundError('type_descr', 'obj_id'),
+                  DIFF_CL_DETAILS),
+                 (errors.IronicAPIError(DETAILS), SAME_DETAILS),
+                 (errors.HeartbeatError(DETAILS), SAME_DETAILS),
+                 (errors.LookupNodeError(DETAILS), SAME_DETAILS),
+                 (errors.LookupAgentIPError(DETAILS), SAME_DETAILS),
+                 (errors.LookupAgentInterfaceError(DETAILS), SAME_DETAILS),
+                 (errors.ImageDownloadError('image_id'), DIFF_CL_DETAILS),
+                 (errors.ImageChecksumError('image_id'), DIFF_CL_DETAILS),
+                 (errors.ImageWriteError('device', 'exit_code', 'stdout',
+                                         'stderr'),
+                  DIFF_CL_DETAILS),
+                 (errors.ConfigDriveTooLargeError('filename', 'filesize'),
+                  DIFF_CL_DETAILS),
+                 (errors.ConfigDriveWriteError('device', 'exit_code', 'stdout',
+                                               'stderr'),
+                  DIFF_CL_DETAILS),
+                 (errors.SystemRebootError('exit_code', 'stdout', 'stderr'),
+                  DIFF_CL_DETAILS),
+                 (errors.BlockDeviceEraseError(DETAILS), SAME_DETAILS),
+                 (errors.BlockDeviceError(DETAILS), SAME_DETAILS),
+                 (errors.VirtualMediaBootError(DETAILS), SAME_DETAILS),
+                 (errors.HardwareManagerMethodNotFound('method'),
+                  DIFF_CL_DETAILS),
+                 (errors.IncompatibleHardwareMethodError(), SAME_CL_MSG),
+                 (errors.IncompatibleHardwareMethodError(DETAILS),
+                  SAME_DETAILS),
+                ]
+        for (obj, check_details) in cases:
+            self._test_class(obj, check_details)