diff --git a/include/class_exceptions.inc b/include/class_exceptions.inc
index e127526cd259a6efe5109a893319e2c6514c0e3d..10fa9fc6270e630cdcdf66195d912a4b62034caf 100644
--- a/include/class_exceptions.inc
+++ b/include/class_exceptions.inc
@@ -28,6 +28,15 @@
 */
 class FusionDirectoryException extends Exception
 {
+  public function toArray (): array
+  {
+    return [
+      'class'   => get_class($this),
+      'message' => $this->getMessage(),
+      'line'    => $this->getLine(),
+      'file'    => $this->getFile(),
+    ];
+  }
 }
 
 /*! \class LDIFImportException
diff --git a/include/errors/class_FusionDirectoryError.inc b/include/errors/class_FusionDirectoryError.inc
index 418c3164b05d7a2161f2dc0a4fa08c0ac35ba96c..6a694270da7afdd18986b59391aae014f42a75b9 100644
--- a/include/errors/class_FusionDirectoryError.inc
+++ b/include/errors/class_FusionDirectoryError.inc
@@ -39,6 +39,7 @@ class FusionDirectoryError extends Error
   public function toArray (): array
   {
     return [
+      'class'   => get_class($this),
       'message' => $this->getMessage(),
       'line'    => $this->getLine(),
       'file'    => $this->getFile(),
diff --git a/include/simpleplugin/attributes/class_BooleanAttribute.inc b/include/simpleplugin/attributes/class_BooleanAttribute.inc
index 52ab02ac7090d75706384fb648a7767bb63054e3..a89c136aef29095f637e64c6f5e067f2facf183f 100644
--- a/include/simpleplugin/attributes/class_BooleanAttribute.inc
+++ b/include/simpleplugin/attributes/class_BooleanAttribute.inc
@@ -166,7 +166,10 @@ class BooleanAttribute extends Attribute
   function deserializeValue ($value)
   {
     if ($this->disabled) {
-      return sprintf(_('Attribute %s is disabled, its value could not be set'), $this->getLdapName());
+      return new SimplePluginError(
+        $this,
+        htmlescape(sprintf(_('Attribute %s is disabled, its value could not be set'), $this->getLdapName()))
+      );
     }
     if ($value === $this->trueValue) {
       $this->setValue(TRUE);
@@ -179,7 +182,10 @@ class BooleanAttribute extends Attribute
     } elseif ($value === 0) {
       $this->setValue(FALSE);
     } else {
-      return sprintf(_('"%s" is not a valid value for attribute "%s" should be "%s" or "%s"'), $value, $this->getLdapName(), $this->trueValue, $this->falseValue);
+      return new SimplePluginError(
+        $this,
+        htmlescape(sprintf(_('"%s" is not a valid value, should be "%s" or "%s"'), $value, $this->getLdapName(), $this->trueValue, $this->falseValue))
+      );
     }
 
     /* No error */
diff --git a/include/simpleplugin/attributes/class_FileAttribute.inc b/include/simpleplugin/attributes/class_FileAttribute.inc
index 098e3988772c17a2cd6d2d98768fd54405da27f7..05abb5e686c0fddb514033b4414d56228a2d80dd 100644
--- a/include/simpleplugin/attributes/class_FileAttribute.inc
+++ b/include/simpleplugin/attributes/class_FileAttribute.inc
@@ -134,12 +134,18 @@ class FileAttribute extends Attribute
   function deserializeValue ($value)
   {
     if ($this->disabled) {
-      return sprintf(_('Attribute %s is disabled, its value could not be set'), $this->getLdapName());
+      return new SimplePluginError(
+        $this,
+        htmlescape(sprintf(_('Attribute %s is disabled, its value could not be set'), $this->getLdapName()))
+      );
     }
     if ($this->binary) {
       $data = base64_decode($value, TRUE);
       if ($data === FALSE) {
-        return sprintf(_('Invalid base64 data for attribute %s'), $this->getLdapName());
+        return new SimplePluginError(
+          $this,
+          htmlescape(_('Invalid base64 data'))
+        );
       }
       $this->setValue($data);
     } else {
@@ -394,14 +400,13 @@ class ImageAttribute extends FileAttribute
         }
       } catch (ImagickException $e) {
         /* Store the exception to return it in deserializeValue() */
-        $this->imagickException = $e;
-        $error = new SimplePluginError(
+        $this->imagickException = new SimplePluginError(
           $this,
           SimplePluginCheckError::invalidValue($e->getMessage()),
           0,
           $e
         );
-        $error->display();
+        $this->imagickException->display();
       }
     } else {
       $error = new SimplePluginError(
@@ -423,7 +428,7 @@ class ImageAttribute extends FileAttribute
       return $error;
     }
     if ($this->imagickException !== NULL) {
-      return sprintf(_('Invalid data, Imagick error: "%s"'), $this->imagickException->getMessage());
+      return $this->imagickException;
     }
   }
 
diff --git a/include/simpleplugin/class_Attribute.inc b/include/simpleplugin/class_Attribute.inc
index c7d4d8729073dbf4ea653bbfa6a8a0049e13fa7b..2d298f490387ff4515492d436b63fbb99c0bd50e 100644
--- a/include/simpleplugin/class_Attribute.inc
+++ b/include/simpleplugin/class_Attribute.inc
@@ -695,7 +695,10 @@ class Attribute
   function deserializeValue ($value)
   {
     if ($this->disabled) {
-      return sprintf(_('Attribute %s is disabled, its value could not be set'), $this->getLdapName());
+      return new SimplePluginError(
+        $this,
+        htmlescape(sprintf(_('Attribute %s is disabled, its value could not be set'), $this->getLdapName()))
+      );
     }
     $this->setValue($value);
   }
diff --git a/include/simpleplugin/class_simplePlugin.inc b/include/simpleplugin/class_simplePlugin.inc
index 55dc16356ab4fe3e73d2ca1a2105a0b976257f51..7dff3485ed1caa6b07ec37a41ca85af10f4ad44e 100644
--- a/include/simpleplugin/class_simplePlugin.inc
+++ b/include/simpleplugin/class_simplePlugin.inc
@@ -2059,10 +2059,13 @@ class simplePlugin implements SimpleTab
             return $error;
           }
         } else {
-          return msgPool::permModify($this->dn, $name);
+          return new SimplePluginPermissionError($this, msgPool::permModify($this->dn, $name));
         }
       } else {
-        return sprintf(_('Unknown field "%s"'), $name);
+        return new SimplePluginError(
+          $this,
+          htmlescape(sprintf(_('Unknown field "%s"'), $name))
+        );
       }
     }
     return TRUE;
diff --git a/plugins/personal/generic/class_UserPasswordAttribute.inc b/plugins/personal/generic/class_UserPasswordAttribute.inc
index 230002399624549b4e8338156d0dd3af4b4764d3..1c7fc460c84bba957f053f60ca437e18ab6d5a77 100644
--- a/plugins/personal/generic/class_UserPasswordAttribute.inc
+++ b/plugins/personal/generic/class_UserPasswordAttribute.inc
@@ -273,17 +273,29 @@ class UserPasswordAttribute extends CompositeAttribute
     }
     if (is_array($value)) {
       if (count($value) > 5) {
-        return sprintf(_('Too many elements in array value for password field %s: %d instead of %d'), $this->getLdapName(), count($value), 5);
+        return new SimplePluginError(
+          $this,
+          htmlescape(sprintf(_('Too many elements in array value: %d instead of %d'), $this->getLdapName(), count($value), 5))
+        );
       } elseif (count($value) < 5) {
-        return sprintf(_('Not enough elements in array value for password field %s: %d instead of %d'), $this->getLdapName(), count($value), 5);
+        return new SimplePluginError(
+          $this,
+          htmlescape(sprintf(_('Not enough elements in array value: %d instead of %d'), $this->getLdapName(), count($value), 5))
+        );
       } elseif (!isset($value[0])) {
-        return sprintf(_('Array value for password field %s must have numeric keys'), $this->getLdapName());
+        return new SimplePluginError(
+          $this,
+          htmlescape(_('Array value for password field must have numeric keys'))
+        );
       }
       $this->setValue($value);
     } elseif (is_string($value)) {
       $this->setValue(['', $value, $value, '', FALSE]);
     } else {
-      return sprintf(_('Invalid value type for password field %s, must be array or string'), $this->getLdapName());
+      return new SimplePluginError(
+        $this,
+        htmlescape(_('Invalid value type for password field, must be array or string'))
+      );
     }
   }
 }