From daba6d766df643cb25c517bc06292b5812775c0d Mon Sep 17 00:00:00 2001
From: Martin Weise <martin.weise@tuwien.ac.at>
Date: Fri, 1 Dec 2023 13:30:58 +0100
Subject: [PATCH] Better error message handling in the frontend

- Propagation way more transparent to users
- Add fallback message in case no error message from backend

ref #396
---
 dbrepo-metadata-db/setup-schema.sql           |  8 +--
 .../exception/AccessDeniedException.java      |  2 +-
 .../at/tuwien/exception/AmqpException.java    |  2 +-
 .../ArbitraryPrimaryKeysException.java        |  2 +-
 .../BannerMessageNotFoundException.java       |  2 +-
 .../exception/BrokerMalformedException.java   |  2 +-
 .../exception/BrokerRemoteException.java      |  2 +-
 .../BrokerVirtualHostGrantException.java      |  2 +-
 ...rokerVirtualHostModificationException.java |  2 +-
 .../exception/ColumnParseException.java       |  2 +-
 .../exception/ConceptNotFoundException.java   |  2 +-
 .../exception/ContainerNotFoundException.java |  2 +-
 .../ContainerStillRunningException.java       |  8 +--
 .../exception/DataDbSidecarException.java     |  2 +-
 .../exception/DataProcessingException.java    |  2 +-
 .../DatabaseConnectionException.java          |  2 +-
 .../exception/DatabaseMalformedException.java |  2 +-
 .../DatabaseNameExistsException.java          |  2 +-
 .../exception/DatabaseNotFoundException.java  |  2 +-
 .../exception/DoiNotFoundException.java       |  2 +-
 .../exception/ExchangeNotFoundException.java  |  2 +-
 .../exception/FileStorageException.java       |  2 +-
 .../exception/FilterBadRequestException.java  |  2 +-
 .../exception/HeaderInvalidException.java     |  2 +-
 .../IdentifierAlreadyExistsException.java     |  2 +-
 .../IdentifierAlreadyPublishedException.java  |  2 +-
 .../IdentifierNotFoundException.java          |  2 +-
 ...entifierPublishingNotAllowedException.java |  2 +-
 .../exception/IdentifierRequestException.java |  2 +-
 .../IdentifierUpdateBadFormException.java     |  2 +-
 .../ImageAlreadyExistsException.java          |  8 +--
 .../exception/ImageInvalidException.java      |  8 +--
 .../exception/ImageNotSupportedException.java |  2 +-
 .../exception/InvalidPrefixException.java     |  2 +-
 .../exception/KeycloakRemoteException.java    |  2 +-
 .../tuwien/exception/NotAllowedException.java |  2 +-
 .../exception/OntologyNotFoundException.java  |  2 +-
 .../exception/OrcidNotFoundException.java     |  2 +-
 .../tuwien/exception/PaginationException.java |  2 +-
 .../exception/PersistenceException.java       |  2 +-
 .../QueryAlreadyPersistedException.java       |  2 +-
 .../exception/QueryMalformedException.java    |  2 +-
 .../exception/QueryNotFoundException.java     |  2 +-
 .../tuwien/exception/QueryStoreException.java |  2 +-
 .../exception/QueueNotFoundException.java     |  2 +-
 .../exception/RealmNotFoundException.java     |  2 +-
 .../exception/RemoteUnavailableException.java |  2 +-
 .../exception/RoleNotFoundException.java      |  2 +-
 .../exception/RorNotFoundException.java       |  2 +-
 .../SemanticEntityNotFoundException.java      |  2 +-
 .../SemanticEntityPersistException.java       |  2 +-
 .../at/tuwien/exception/SortException.java    |  2 +-
 .../TableColumnNotFoundException.java         |  2 +-
 .../exception/TableMalformedException.java    |  2 +-
 .../exception/TableNameExistsException.java   |  2 +-
 .../exception/TableNotFoundException.java     |  2 +-
 .../exception/TupleDeleteException.java       |  2 +-
 .../exception/UnitNotFoundException.java      |  2 +-
 .../exception/UriMalformedException.java      |  2 +-
 .../UserAttributeNotFoundException.java       |  2 +-
 .../exception/ViewMalformedException.java     |  2 +-
 .../repository/mdb/TableRepository.java       |  2 +
 .../endpoints/TableEndpointUnitTest.java      | 29 ++++++++
 .../TableServiceIntegrationWriteTest.java     |  3 +
 .../java/at/tuwien/service/TableService.java  | 37 +++++-----
 .../main/java/at/tuwien/test/BaseTest.java    |  9 ++-
 dbrepo-ui/api/analyse.service.js              |  7 +-
 dbrepo-ui/api/container.service.js            | 15 ++--
 dbrepo-ui/api/identifier.service.js           | 31 +++------
 dbrepo-ui/api/index.js                        | 10 +--
 dbrepo-ui/api/metadata.service.js             | 27 ++------
 dbrepo-ui/api/middleware.service.js           |  6 +-
 dbrepo-ui/api/query.service.js                | 69 ++++---------------
 dbrepo-ui/api/search.service.js               | 15 ++--
 dbrepo-ui/api/semantic.service.js             | 20 +++---
 dbrepo-ui/api/table.mapper.js                 | 10 +++
 dbrepo-ui/api/table.service.js                | 14 ++++
 dbrepo-ui/components/TableSchema.vue          | 26 ++-----
 dbrepo-ui/components/TableToolbar.vue         |  1 -
 .../database/_database_id/table/import.vue    | 62 ++++++++++-------
 80 files changed, 257 insertions(+), 282 deletions(-)

diff --git a/dbrepo-metadata-db/setup-schema.sql b/dbrepo-metadata-db/setup-schema.sql
index 1f46bf29cf..0b3a6c132d 100644
--- a/dbrepo-metadata-db/setup-schema.sql
+++ b/dbrepo-metadata-db/setup-schema.sql
@@ -221,7 +221,7 @@ CREATE TABLE IF NOT EXISTS `mdb_constraints_foreign_key`
     on_delete VARCHAR(50) NULL,
     position  INT         NULL,
     PRIMARY KEY (fkid),
-    FOREIGN KEY (tid) REFERENCES mdb_tables (id),
+    FOREIGN KEY (tid) REFERENCES mdb_tables (id) ON DELETE CASCADE,
     FOREIGN KEY (rtid) REFERENCES mdb_tables (id)
 ) WITH SYSTEM VERSIONING;
 
@@ -243,7 +243,7 @@ CREATE TABLE IF NOT EXISTS `mdb_constraints_unique`
     tid      BIGINT NOT NULL,
     position INT    NULL,
     PRIMARY KEY (uid),
-    FOREIGN KEY (tid) REFERENCES mdb_tables (id)
+    FOREIGN KEY (tid) REFERENCES mdb_tables (id) ON DELETE CASCADE
 );
 
 CREATE TABLE IF NOT EXISTS `mdb_constraints_unique_columns`
@@ -253,7 +253,7 @@ CREATE TABLE IF NOT EXISTS `mdb_constraints_unique_columns`
     cid BIGINT NOT NULL,
     PRIMARY KEY (id),
     FOREIGN KEY (uid) REFERENCES mdb_constraints_unique (uid),
-    FOREIGN KEY (cid) REFERENCES mdb_columns (id)
+    FOREIGN KEY (cid) REFERENCES mdb_columns (id) ON DELETE CASCADE
 ) WITH SYSTEM VERSIONING;
 
 CREATE TABLE IF NOT EXISTS `mdb_constraints_checks`
@@ -262,7 +262,7 @@ CREATE TABLE IF NOT EXISTS `mdb_constraints_checks`
     tid    BIGINT       NOT NULL,
     checks VARCHAR(255) NOT NULL,
     PRIMARY KEY (id),
-    FOREIGN KEY (tid) REFERENCES mdb_tables (id)
+    FOREIGN KEY (tid) REFERENCES mdb_tables (id) ON DELETE CASCADE
 ) WITH SYSTEM VERSIONING;
 
 CREATE TABLE IF NOT EXISTS `mdb_concepts`
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessDeniedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessDeniedException.java
index 84169f32e0..a13b3f6016 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessDeniedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AccessDeniedException.java
@@ -13,7 +13,7 @@ public class AccessDeniedException extends IOException {
     }
 
     public AccessDeniedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public AccessDeniedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AmqpException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AmqpException.java
index da70a16dd3..68da501b06 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AmqpException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/AmqpException.java
@@ -11,7 +11,7 @@ public class AmqpException extends Exception {
     }
 
     public AmqpException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public AmqpException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ArbitraryPrimaryKeysException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ArbitraryPrimaryKeysException.java
index 0b64444423..68bdb76470 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ArbitraryPrimaryKeysException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ArbitraryPrimaryKeysException.java
@@ -11,7 +11,7 @@ public class ArbitraryPrimaryKeysException extends Exception {
     }
 
     public ArbitraryPrimaryKeysException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ArbitraryPrimaryKeysException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BannerMessageNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BannerMessageNotFoundException.java
index e4587b1453..75693577cb 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BannerMessageNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BannerMessageNotFoundException.java
@@ -11,7 +11,7 @@ public class BannerMessageNotFoundException extends Exception {
     }
 
     public BannerMessageNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public BannerMessageNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerMalformedException.java
index 975982aeac..a448be4606 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerMalformedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerMalformedException.java
@@ -13,7 +13,7 @@ public class BrokerMalformedException extends IOException {
     }
 
     public BrokerMalformedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public BrokerMalformedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerRemoteException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerRemoteException.java
index 922462d2ee..0d3a1b988b 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerRemoteException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerRemoteException.java
@@ -11,7 +11,7 @@ public class BrokerRemoteException extends Exception {
     }
 
     public BrokerRemoteException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public BrokerRemoteException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostGrantException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostGrantException.java
index 43c9b928a6..4e06e3f843 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostGrantException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostGrantException.java
@@ -11,7 +11,7 @@ public class BrokerVirtualHostGrantException extends Exception {
     }
 
     public BrokerVirtualHostGrantException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public BrokerVirtualHostGrantException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostModificationException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostModificationException.java
index a9fda0c9d4..5f7420d056 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostModificationException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/BrokerVirtualHostModificationException.java
@@ -11,7 +11,7 @@ public class BrokerVirtualHostModificationException extends Exception {
     }
 
     public BrokerVirtualHostModificationException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public BrokerVirtualHostModificationException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ColumnParseException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ColumnParseException.java
index c0c1e109de..8b81d04452 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ColumnParseException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ColumnParseException.java
@@ -11,7 +11,7 @@ public class ColumnParseException extends Exception {
     }
 
     public ColumnParseException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ColumnParseException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java
index f85cd6846a..490b3c78dc 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ConceptNotFoundException.java
@@ -11,7 +11,7 @@ public class ConceptNotFoundException extends Exception {
     }
 
     public ConceptNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ConceptNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java
index 85d49d4cb3..40fc0dd4e1 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerNotFoundException.java
@@ -11,7 +11,7 @@ public class ContainerNotFoundException extends Exception {
     }
 
     public ContainerNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ContainerNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerStillRunningException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerStillRunningException.java
index 0eeceada67..7799caa84f 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerStillRunningException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ContainerStillRunningException.java
@@ -10,12 +10,12 @@ public class ContainerStillRunningException extends Exception {
         super(msg);
     }
 
-    public ContainerStillRunningException(String msg, Throwable e) {
-        super(msg, e);
+    public ContainerStillRunningException(String msg, Throwable thr) {
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
-    public ContainerStillRunningException(Throwable e) {
-        super(e);
+    public ContainerStillRunningException(Throwable thr) {
+        super(thr);
     }
 
 }
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataDbSidecarException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataDbSidecarException.java
index 036b23f631..7258ad1755 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataDbSidecarException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataDbSidecarException.java
@@ -13,7 +13,7 @@ public class DataDbSidecarException extends IOException {
     }
 
     public DataDbSidecarException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DataDbSidecarException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataProcessingException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataProcessingException.java
index 873eb5d282..fd86efc2b2 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataProcessingException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DataProcessingException.java
@@ -11,7 +11,7 @@ public class DataProcessingException extends Exception {
     }
 
     public DataProcessingException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DataProcessingException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseConnectionException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseConnectionException.java
index 1296c64371..a1d8dc0d26 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseConnectionException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseConnectionException.java
@@ -11,7 +11,7 @@ public class DatabaseConnectionException extends Exception {
     }
 
     public DatabaseConnectionException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DatabaseConnectionException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java
index 1775380783..1f9b8295c7 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseMalformedException.java
@@ -13,7 +13,7 @@ public class DatabaseMalformedException extends IOException {
     }
 
     public DatabaseMalformedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DatabaseMalformedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNameExistsException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNameExistsException.java
index 68e1948138..86926b7016 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNameExistsException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNameExistsException.java
@@ -13,7 +13,7 @@ public class DatabaseNameExistsException extends IOException {
     }
 
     public DatabaseNameExistsException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DatabaseNameExistsException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java
index 3c22d6ea35..d3c463cd9a 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DatabaseNotFoundException.java
@@ -11,7 +11,7 @@ public class DatabaseNotFoundException extends Exception {
     }
 
     public DatabaseNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DatabaseNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java
index 4530e1e996..dc03edf81e 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/DoiNotFoundException.java
@@ -11,7 +11,7 @@ public class DoiNotFoundException extends Exception {
     }
 
     public DoiNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public DoiNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java
index fdaa0e3cfd..8b6620fed5 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ExchangeNotFoundException.java
@@ -11,7 +11,7 @@ public class ExchangeNotFoundException extends Exception {
     }
 
     public ExchangeNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ExchangeNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FileStorageException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FileStorageException.java
index 21968a6e68..9ec3f4f0df 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FileStorageException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FileStorageException.java
@@ -11,7 +11,7 @@ public class FileStorageException extends Exception {
     }
 
     public FileStorageException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public FileStorageException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java
index 7364f797a3..3fb7909013 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/FilterBadRequestException.java
@@ -11,7 +11,7 @@ public class FilterBadRequestException extends Exception {
     }
 
     public FilterBadRequestException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public FilterBadRequestException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/HeaderInvalidException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/HeaderInvalidException.java
index 87b7da4e97..ca6e829d3b 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/HeaderInvalidException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/HeaderInvalidException.java
@@ -11,7 +11,7 @@ public class HeaderInvalidException extends Exception {
     }
 
     public HeaderInvalidException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public HeaderInvalidException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyExistsException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyExistsException.java
index e913485aad..706eeac06d 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyExistsException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyExistsException.java
@@ -11,7 +11,7 @@ public class IdentifierAlreadyExistsException extends Exception {
     }
 
     public IdentifierAlreadyExistsException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public IdentifierAlreadyExistsException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyPublishedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyPublishedException.java
index fefe477205..e8c23984b2 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyPublishedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierAlreadyPublishedException.java
@@ -11,7 +11,7 @@ public class IdentifierAlreadyPublishedException extends Exception {
     }
 
     public IdentifierAlreadyPublishedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public IdentifierAlreadyPublishedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java
index 9a844d7651..c4c2ead188 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierNotFoundException.java
@@ -11,7 +11,7 @@ public class IdentifierNotFoundException extends Exception {
     }
 
     public IdentifierNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public IdentifierNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierPublishingNotAllowedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierPublishingNotAllowedException.java
index b2748cb9a7..9623c55919 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierPublishingNotAllowedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierPublishingNotAllowedException.java
@@ -11,7 +11,7 @@ public class IdentifierPublishingNotAllowedException extends Exception {
     }
 
     public IdentifierPublishingNotAllowedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public IdentifierPublishingNotAllowedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierRequestException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierRequestException.java
index ef20713d6f..3999c47bc9 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierRequestException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierRequestException.java
@@ -11,7 +11,7 @@ public class IdentifierRequestException extends Exception {
     }
 
     public IdentifierRequestException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public IdentifierRequestException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierUpdateBadFormException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierUpdateBadFormException.java
index 884a5d4bc5..b71955e757 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierUpdateBadFormException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/IdentifierUpdateBadFormException.java
@@ -11,7 +11,7 @@ public class IdentifierUpdateBadFormException extends Exception {
     }
 
     public IdentifierUpdateBadFormException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public IdentifierUpdateBadFormException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java
index 9b52af25ff..ff6d236fc4 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageAlreadyExistsException.java
@@ -10,12 +10,12 @@ public class ImageAlreadyExistsException extends Exception {
         super(msg);
     }
 
-    public ImageAlreadyExistsException(String msg, Throwable e) {
-        super(msg, e);
+    public ImageAlreadyExistsException(String msg, Throwable thr) {
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
-    public ImageAlreadyExistsException(Throwable e) {
-        super(e);
+    public ImageAlreadyExistsException(Throwable thr) {
+        super(thr);
     }
 
 }
\ No newline at end of file
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java
index 5cfc720a4c..93a7a30912 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageInvalidException.java
@@ -10,12 +10,12 @@ public class ImageInvalidException extends Exception {
         super(msg);
     }
 
-    public ImageInvalidException(String msg, Throwable e) {
-        super(msg, e);
+    public ImageInvalidException(String msg, Throwable thr) {
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
-    public ImageInvalidException(Throwable e) {
-        super(e);
+    public ImageInvalidException(Throwable thr) {
+        super(thr);
     }
 
 }
\ No newline at end of file
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotSupportedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotSupportedException.java
index 1d293e03e5..c37d2d07a4 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotSupportedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ImageNotSupportedException.java
@@ -11,7 +11,7 @@ public class ImageNotSupportedException extends Exception {
     }
 
     public ImageNotSupportedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ImageNotSupportedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/InvalidPrefixException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/InvalidPrefixException.java
index d14264a53c..0a51bf42b0 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/InvalidPrefixException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/InvalidPrefixException.java
@@ -11,7 +11,7 @@ public class InvalidPrefixException extends Exception {
     }
 
     public InvalidPrefixException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public InvalidPrefixException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/KeycloakRemoteException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/KeycloakRemoteException.java
index 6616739278..f4898eba1e 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/KeycloakRemoteException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/KeycloakRemoteException.java
@@ -11,7 +11,7 @@ public class KeycloakRemoteException extends Exception {
     }
 
     public KeycloakRemoteException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public KeycloakRemoteException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java
index b1521fe940..f7bc6f69f7 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/NotAllowedException.java
@@ -11,7 +11,7 @@ public class NotAllowedException extends Exception {
     }
 
     public NotAllowedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public NotAllowedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java
index cb82fc0b9a..df590e0669 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OntologyNotFoundException.java
@@ -11,7 +11,7 @@ public class OntologyNotFoundException extends Exception {
     }
 
     public OntologyNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public OntologyNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java
index 0f87985305..13414f10e1 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/OrcidNotFoundException.java
@@ -11,7 +11,7 @@ public class OrcidNotFoundException extends Exception {
     }
 
     public OrcidNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public OrcidNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java
index 9d56aec9c2..11b8aecc87 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PaginationException.java
@@ -11,7 +11,7 @@ public class PaginationException extends Exception {
     }
 
     public PaginationException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public PaginationException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PersistenceException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PersistenceException.java
index 92c1d6f4b9..44bf9da7ed 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PersistenceException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/PersistenceException.java
@@ -11,7 +11,7 @@ public class PersistenceException extends Exception {
    }
 
    public PersistenceException(String msg, Throwable thr) {
-       super(msg, thr);
+       super(msg + ": " + thr.getLocalizedMessage(), thr);
    }
 
     public PersistenceException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryAlreadyPersistedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryAlreadyPersistedException.java
index 48d3bb0ad9..4192625527 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryAlreadyPersistedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryAlreadyPersistedException.java
@@ -11,7 +11,7 @@ public class QueryAlreadyPersistedException extends Exception {
     }
 
     public QueryAlreadyPersistedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public QueryAlreadyPersistedException(Throwable thr) { super(thr);
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java
index 6d3d2bc052..18fdc50074 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryMalformedException.java
@@ -11,7 +11,7 @@ public class QueryMalformedException extends Exception {
     }
 
     public QueryMalformedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public QueryMalformedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java
index a5e9075489..003a85046b 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryNotFoundException.java
@@ -11,7 +11,7 @@ public class QueryNotFoundException extends Exception {
     }
 
     public QueryNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public QueryNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreException.java
index d07cd0df4a..388a35a85f 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueryStoreException.java
@@ -11,7 +11,7 @@ public class QueryStoreException extends Exception {
     }
 
     public QueryStoreException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public QueryStoreException(Throwable thr) { super(thr);
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java
index b5c6aed7ff..7ee465aab5 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/QueueNotFoundException.java
@@ -11,7 +11,7 @@ public class QueueNotFoundException extends Exception {
     }
 
     public QueueNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public QueueNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RealmNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RealmNotFoundException.java
index 1750cfb525..1b69a01df8 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RealmNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RealmNotFoundException.java
@@ -11,7 +11,7 @@ public class RealmNotFoundException extends Exception {
     }
 
     public RealmNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public RealmNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java
index 3f6700d06b..3c2a177439 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RemoteUnavailableException.java
@@ -11,7 +11,7 @@ public class RemoteUnavailableException extends Exception {
     }
 
     public RemoteUnavailableException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public RemoteUnavailableException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RoleNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RoleNotFoundException.java
index 8430d64d76..21caf8b8bd 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RoleNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RoleNotFoundException.java
@@ -11,7 +11,7 @@ public class RoleNotFoundException extends Exception {
     }
 
     public RoleNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public RoleNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java
index e22cad5c36..f6a188e185 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/RorNotFoundException.java
@@ -11,7 +11,7 @@ public class RorNotFoundException extends Exception {
     }
 
     public RorNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public RorNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java
index 70098f61da..2903da9a48 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityNotFoundException.java
@@ -11,7 +11,7 @@ public class SemanticEntityNotFoundException extends Exception {
     }
 
     public SemanticEntityNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public SemanticEntityNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityPersistException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityPersistException.java
index e33560e942..a46ae85be0 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityPersistException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SemanticEntityPersistException.java
@@ -11,7 +11,7 @@ public class SemanticEntityPersistException extends Exception {
     }
 
     public SemanticEntityPersistException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public SemanticEntityPersistException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java
index 7415590ad6..b15e055793 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SortException.java
@@ -11,7 +11,7 @@ public class SortException extends Exception {
     }
 
     public SortException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public SortException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableColumnNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableColumnNotFoundException.java
index e83abd5eef..1de886ca19 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableColumnNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableColumnNotFoundException.java
@@ -11,7 +11,7 @@ public class TableColumnNotFoundException extends Exception {
     }
 
     public TableColumnNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public TableColumnNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java
index fb232e7155..d4de12d91b 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableMalformedException.java
@@ -11,7 +11,7 @@ public class TableMalformedException extends Exception {
     }
 
     public TableMalformedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public TableMalformedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNameExistsException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNameExistsException.java
index e1251f4b5f..6650c0ac31 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNameExistsException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNameExistsException.java
@@ -11,7 +11,7 @@ public class TableNameExistsException extends Exception {
     }
 
     public TableNameExistsException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public TableNameExistsException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java
index 89fa3ed467..57146ca8c6 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TableNotFoundException.java
@@ -11,7 +11,7 @@ public class TableNotFoundException extends Exception {
     }
 
     public TableNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public TableNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TupleDeleteException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TupleDeleteException.java
index 87e5e4a483..55b034c7b3 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TupleDeleteException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/TupleDeleteException.java
@@ -11,7 +11,7 @@ public class TupleDeleteException extends Exception {
     }
 
     public TupleDeleteException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public TupleDeleteException(Throwable thr) { super(thr);
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java
index 6a5e1ddf60..2d67d3bc5e 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UnitNotFoundException.java
@@ -11,7 +11,7 @@ public class UnitNotFoundException extends Exception {
     }
 
     public UnitNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public UnitNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java
index 92f102fb56..b886796074 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UriMalformedException.java
@@ -11,7 +11,7 @@ public class UriMalformedException extends Exception {
     }
 
     public UriMalformedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public UriMalformedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserAttributeNotFoundException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserAttributeNotFoundException.java
index f0d3249868..2ceb33a0f7 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserAttributeNotFoundException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/UserAttributeNotFoundException.java
@@ -11,7 +11,7 @@ public class UserAttributeNotFoundException extends Exception {
     }
 
     public UserAttributeNotFoundException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public UserAttributeNotFoundException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java
index 5dfdaf170e..fc96d29c32 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/ViewMalformedException.java
@@ -11,7 +11,7 @@ public class ViewMalformedException extends Exception {
     }
 
     public ViewMalformedException(String msg, Throwable thr) {
-        super(msg, thr);
+        super(msg + ": " + thr.getLocalizedMessage(), thr);
     }
 
     public ViewMalformedException(Throwable thr) {
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/mdb/TableRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/mdb/TableRepository.java
index 314c23ab0b..4ee22add4f 100644
--- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/mdb/TableRepository.java
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/mdb/TableRepository.java
@@ -26,6 +26,8 @@ public interface TableRepository extends JpaRepository<Table, Long> {
      */
     List<Table> findByDatabaseOrderByCreatedDesc(Database database);
 
+    List<Table> findByInternalName(String internalName);
+
     /**
      * Finds a table with given database and internal name.
      *
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java
index 681f4efebc..21762fad93 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java
@@ -349,6 +349,35 @@ public class TableEndpointUnitTest extends BaseUnitTest {
         assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
     }
 
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_privateHasRoleForeignTable_fails() throws DatabaseNotFoundException, TableNotFoundException {
+
+        /* mock */
+        when(tableService.find(DATABASE_1_ID, TABLE_2_ID))
+                .thenReturn(TABLE_2);
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_delete(DATABASE_1_ID, TABLE_2_ID, DATABASE_1, TABLE_2, USER_1_PRINCIPAL);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_2_USERNAME, authorities = "delete-foreign-table")
+    public void delete_privateHasRoleForeignTable_succeeds() throws DatabaseNotFoundException, TableNotFoundException,
+            NotAllowedException, TableMalformedException, QueryMalformedException, ImageNotSupportedException,
+            ContainerNotFoundException, DataProcessingException {
+
+        /* mock */
+        when(tableService.find(DATABASE_1_ID, TABLE_1_ID))
+                .thenReturn(TABLE_1);
+
+        /* test */
+        final ResponseEntity<?> response = generic_delete(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_2_PRINCIPAL);
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+    }
+
     @Test
     @WithMockUser(username = USER_4_USERNAME)
     public void delete_publicNoRole_fails() {
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java
index c3149bd713..cf4f5f86ed 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java
@@ -97,6 +97,9 @@ public class TableServiceIntegrationWriteTest extends BaseUnitTest {
         databaseRepository.save(DATABASE_1_SIMPLE);
         tableRepository.save(TABLE_1_SIMPLE);
         tableRepository.save(TABLE_2_SIMPLE);
+        /* missing pointers */
+        TABLE_1.setConstraints(TABLE_1_CONSTRAINTS);
+        TABLE_2.setConstraints(TABLE_2_CONSTRAINTS);
     }
 
     @Test
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java
index ef99379904..7b37e4d8b9 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java
@@ -15,8 +15,8 @@ public interface TableService {
     /**
      * Find a table in the metadata database by database-table id tuple
      *
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
+     * @param databaseId The database id.
+     * @param tableId    The table id.
      * @return The database.
      * @throws DatabaseNotFoundException The database is not found.
      * @throws TableNotFoundException    The table is not found.
@@ -33,21 +33,22 @@ public interface TableService {
     /**
      * Find the table history.
      *
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
-     * @param principal   The user principal.
+     * @param databaseId The database id.
+     * @param tableId    The table id.
+     * @param principal  The user principal.
      * @return The history as a list, if successful.
      * @throws QueryMalformedException   The query is malformed.
      * @throws DatabaseNotFoundException The database is not found.
      * @throws TableNotFoundException    The table is not found.
      */
     List<TableHistoryDto> findHistory(Long databaseId, Long tableId, Principal principal)
-            throws DatabaseNotFoundException, QueryMalformedException, TableNotFoundException, DatabaseConnectionException, QueryStoreException, UserNotFoundException;
+            throws DatabaseNotFoundException, QueryMalformedException, TableNotFoundException,
+            DatabaseConnectionException, QueryStoreException, UserNotFoundException;
 
     /**
      * Select all tables from the metadata database.
      *
-     * @param databaseId  The database id.
+     * @param databaseId The database id.
      * @return The list of tables.
      */
     List<Table> findAll(Long databaseId) throws DatabaseNotFoundException;
@@ -55,8 +56,8 @@ public interface TableService {
     /**
      * Deletes a table for a fiven database-table id pair.
      *
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
+     * @param databaseId The database id.
+     * @param tableId    The table id.
      * @throws TableNotFoundException     The table was not found in the metadata database.
      * @throws DatabaseNotFoundException  The database was not found in the metadata database.
      * @throws ImageNotSupportedException The image is not supported.
@@ -70,8 +71,8 @@ public interface TableService {
     /**
      * Find a table by database-table id pair
      *
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
+     * @param databaseId The database id.
+     * @param tableId    The table id.
      * @return The table.
      * @throws TableNotFoundException    The table was not found in the metadata database.
      * @throws DatabaseNotFoundException The database was not found in the metadata database.
@@ -83,9 +84,9 @@ public interface TableService {
     /**
      * Creates a table for a database id with given schema as data
      *
-     * @param databaseId  The database id.
-     * @param createDto   The schema (as data).
-     * @param principal   The principal.
+     * @param databaseId The database id.
+     * @param createDto  The schema (as data).
+     * @param principal  The principal.
      * @return The created table.
      * @throws ImageNotSupportedException The image is not supported.
      * @throws DatabaseNotFoundException  The database was not found in the metadata database.
@@ -101,10 +102,10 @@ public interface TableService {
     /**
      * Updates a table column
      *
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
-     * @param columnId    The column id.
-     * @param updateDto   The update data containing unit and concept uris.
+     * @param databaseId The database id.
+     * @param tableId    The table id.
+     * @param columnId   The column id.
+     * @param updateDto  The update data containing unit and concept uris.
      * @return The updated table column, if successful.
      * @throws TableNotFoundException     The table was not found in the metadata database.
      * @throws DatabaseNotFoundException  The database was not found in the metadata database.
diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java
index 769348786e..50547102ad 100644
--- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java
+++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java
@@ -160,10 +160,10 @@ public abstract class BaseTest {
     public final static String[] ESCALATED_QUERY_HANDLING = new String[]{"escalated-query-handling"};
 
     public final static String[] DEFAULT_TABLE_HANDLING = new String[]{"default-table-handling",
-            "list-tables", "create-table", "modify-table-column-semantics", "find-table"};
+            "list-tables", "create-table", "modify-table-column-semantics", "find-table", "delete-table"};
 
     public final static String[] ESCALATED_TABLE_HANDLING = new String[]{"escalated-table-handling",
-            "delete-table"};
+            "delete-foreign-table"};
 
     public final static String[] DEFAULT_USER_HANDLING = new String[]{"default-user-handling", "modify-user-theme",
             "modify-user-information"};
@@ -3518,7 +3518,10 @@ public abstract class BaseTest {
                             ForeignKeyReference.builder().column(TABLE_1_COLUMNS.get(2)).referencedColumn(TABLE_1_COLUMNS.get(0)).build())
                     ).build()
             ))
-            .uniques(List.of(Unique.builder().columns(List.of(TABLE_1_COLUMNS.get(1))).build()))
+            .uniques(List.of(Unique.builder().columns(List.of(
+                    TABLE_1_COLUMNS.get(0),
+                    TABLE_1_COLUMNS.get(1)
+            )).build()))
             .checks(Set.of("`mintemp` > 0"))
             .build();
 
diff --git a/dbrepo-ui/api/analyse.service.js b/dbrepo-ui/api/analyse.service.js
index a244759d62..b25b051571 100644
--- a/dbrepo-ui/api/analyse.service.js
+++ b/dbrepo-ui/api/analyse.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 
 class AnalyseService {
   determineDataTypes (filename, separator) {
@@ -15,9 +14,7 @@ class AnalyseService {
           resolve(analysis)
         })
         .catch((error) => {
-          const { code, message } = error
-          console.error('Failed to load analysis', error)
-          Vue.$toast.error(`[${code}] Failed to load analysis: ${message}`)
+          displayError('Failed to load analysis', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/container.service.js b/dbrepo-ui/api/container.service.js
index 2d6021c89f..168716512c 100644
--- a/dbrepo-ui/api/container.service.js
+++ b/dbrepo-ui/api/container.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 
 class ContainerService {
   findAll (limit = 100) {
@@ -11,9 +10,7 @@ class ContainerService {
           resolve(containers)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load containers', error)
-          Vue.$toast.error(`[${code}] Failed to load containers: ${message}`)
+          displayError('Failed to load container', error)
           reject(error)
         })
     })
@@ -28,9 +25,7 @@ class ContainerService {
           resolve(container)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load container', error)
-          Vue.$toast.error(`[${code}] Failed to load container: ${message}`)
+          displayError('Failed to load container', error)
           reject(error)
         })
     })
@@ -45,9 +40,7 @@ class ContainerService {
           resolve(image)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load image', error)
-          Vue.$toast.error(`[${code}] Failed to load image: ${message}`)
+          displayError('Failed to load image', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/identifier.service.js b/dbrepo-ui/api/identifier.service.js
index c377aa0326..a214c6d9e7 100644
--- a/dbrepo-ui/api/identifier.service.js
+++ b/dbrepo-ui/api/identifier.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 
 class IdentifierService {
   findAll (databaseId, type) {
@@ -12,9 +11,7 @@ class IdentifierService {
           resolve(identifiers)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load identifiers', error)
-          Vue.$toast.error(`[${code}] Failed to load identifiers: ${message}`)
+          displayError('Failed to load identifiers', error)
           reject(error)
         })
     })
@@ -41,9 +38,7 @@ class IdentifierService {
           }
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load identifier metadata', error)
-          Vue.$toast.error(`[${code}] Failed to load identifier metadata: ${message}`)
+          displayError('Failed to load identifier', error)
           reject(error)
         })
     })
@@ -58,9 +53,7 @@ class IdentifierService {
           resolve(identifier)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load identifier', error)
-          Vue.$toast.error(`[${code}] Failed to load identifier: ${message}`)
+          displayError('Failed to load citation recommendation', error)
           reject(error)
         })
     })
@@ -75,9 +68,7 @@ class IdentifierService {
           resolve(identifier)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to create identifier', error)
-          Vue.$toast.error(`[${code}] Failed to create identifier: ${message}`)
+          displayError('Failed to create identifier', error)
           reject(error)
         })
     })
@@ -92,9 +83,7 @@ class IdentifierService {
           resolve(identifier)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to update identifier', error)
-          Vue.$toast.error(`[${code}] Failed to update identifier: ${message}`)
+          displayError('Failed to update identifier', error)
           reject(error)
         })
     })
@@ -109,9 +98,7 @@ class IdentifierService {
           resolve(identifier)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to export identifier', error)
-          Vue.$toast.error(`[${code}] Failed to export identifier: ${message}`)
+          displayError('Failed to export identifier', error)
           reject(error)
         })
     })
@@ -122,9 +109,7 @@ class IdentifierService {
       api.delete(`/api/pid/${pid}`, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to delete identifier', error)
-          Vue.$toast.error(`[${code}] Failed to delete identifier: ${message}`)
+          displayError('Failed to delete identifier', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/index.js b/dbrepo-ui/api/index.js
index c56e45b3dd..c562536197 100644
--- a/dbrepo-ui/api/index.js
+++ b/dbrepo-ui/api/index.js
@@ -11,15 +11,15 @@ const instance = axios.create({
   baseURL: baseUrl
 })
 
-function displayError (error, warning) {
+function displayError (altMessage, error) {
   const { code, message } = error.response.data
   if (code && message) {
-    console.error(warning, error)
-    Vue.$toast.error(`[${code}] ${warning}: ${message}`)
+    console.error(error)
+    Vue.$toast.error(message)
     return
   }
-  console.error(warning, error)
-  Vue.$toast.error(`[${error.code}] ${warning}: ${error.message}`)
+  console.error(altMessage, error)
+  Vue.$toast.error(`[${error.code}] ${altMessage}: ${error.message}`)
 }
 
 export default instance
diff --git a/dbrepo-ui/api/metadata.service.js b/dbrepo-ui/api/metadata.service.js
index c49d1d952d..9954f9ca91 100644
--- a/dbrepo-ui/api/metadata.service.js
+++ b/dbrepo-ui/api/metadata.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 
 class MetadataService {
   findAllMessages () {
@@ -11,9 +10,7 @@ class MetadataService {
           resolve(messages)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load messages', error)
-          Vue.$toast.error(`[${code}] Failed to load messages: ${message}`)
+          displayError('Failed to load maintenance messages', error)
           reject(error)
         })
     })
@@ -28,9 +25,7 @@ class MetadataService {
           resolve(messages)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to create message', error)
-          Vue.$toast.error(`[${code}] Failed to create message: ${message}`)
+          displayError('Failed to create maintenance message', error)
           reject(error)
         })
     })
@@ -45,9 +40,7 @@ class MetadataService {
           resolve(messages)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to find message', error)
-          Vue.$toast.error(`[${code}] Failed to find message: ${message}`)
+          displayError('Failed to find maintenance message', error)
           reject(error)
         })
     })
@@ -62,9 +55,7 @@ class MetadataService {
           resolve(messages)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to update message', error)
-          Vue.$toast.error(`[${code}] Failed to update message: ${message}`)
+          displayError('Failed to update maintenance message', error)
           reject(error)
         })
     })
@@ -75,9 +66,7 @@ class MetadataService {
       api.delete(`/api/maintenance/message/${id}`, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to delete message', error)
-          Vue.$toast.error(`[${code}] Failed to delete message: ${message}`)
+          displayError('Failed to delete maintenance message', error)
           reject(error)
         })
     })
@@ -92,9 +81,7 @@ class MetadataService {
           resolve(messages)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load active messages', error)
-          Vue.$toast.error(`[${code}] Failed to load active messages: ${message}`)
+          displayError('Failed to load active maintenance messages', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/middleware.service.js b/dbrepo-ui/api/middleware.service.js
index be56c223bb..11377428ee 100644
--- a/dbrepo-ui/api/middleware.service.js
+++ b/dbrepo-ui/api/middleware.service.js
@@ -1,5 +1,5 @@
-import Vue from 'vue'
 import axios from 'axios'
+import { displayError } from '@/api/index'
 
 class MiddlewareService {
   buildQuery (data) {
@@ -11,9 +11,7 @@ class MiddlewareService {
           resolve(file)
         })
         .catch((error) => {
-          const { code, message } = error
-          console.error('Failed to build query', error)
-          Vue.$toast.error(`[${code}] Failed to build query: ${message}`)
+          displayError('Failed to build query', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/query.service.js b/dbrepo-ui/api/query.service.js
index 8f8488d647..5029b562ae 100644
--- a/dbrepo-ui/api/query.service.js
+++ b/dbrepo-ui/api/query.service.js
@@ -1,5 +1,4 @@
-import Vue from 'vue'
-import api from '@/api'
+import api, { displayError } from '@/api'
 
 class QueryService {
   findAll (databaseId, persisted) {
@@ -11,9 +10,7 @@ class QueryService {
           resolve(queries)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load queries', error)
-          Vue.$toast.error(`[${code}] Failed to load queries: ${message}`)
+          displayError('Failed to load queries', error)
           reject(error)
         })
     })
@@ -27,9 +24,7 @@ class QueryService {
           console.debug('response query', query)
           resolve(query)
         }).catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to load query', error)
-          Vue.$toast.error(`[${code}] Failed to load query: ${message}`)
+          displayError('Failed to load query', error)
           reject(error)
         })
     })
@@ -44,9 +39,7 @@ class QueryService {
           resolve(query)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to persist query', error)
-          Vue.$toast.error(`[${code}] Failed to persist query: ${message}`)
+          displayError('Failed to persist query', error)
           reject(error)
         })
     })
@@ -61,9 +54,7 @@ class QueryService {
           resolve(table)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to import csv to table', error)
-          Vue.$toast.error(`[${code}] Failed to import csv to table: ${message}`)
+          displayError('Failed to import csv to table', error)
           reject(error)
         })
     })
@@ -78,14 +69,7 @@ class QueryService {
           resolve(tuple)
         })
         .catch((error) => {
-          const { status } = error
-          const { code, message } = error.response.data
-          if (status === 423) {
-            console.error('Database failed to accept tuple', error)
-          } else {
-            console.error('Failed to insert tuple', error)
-          }
-          Vue.$toast.error(`[${code}] Failed to insert tuple: ${message}`)
+          displayError('Failed to insert tuple', error)
           reject(error)
         })
     })
@@ -100,14 +84,7 @@ class QueryService {
           resolve(tuple)
         })
         .catch((error) => {
-          const { status } = error
-          const { code, message } = error.response.data
-          if (status === 423) {
-            console.error('Database failed to accept tuple', error)
-          } else {
-            console.error('Failed to update tuple', error)
-          }
-          Vue.$toast.error(`[${code}] Failed to update tuple: ${message}`)
+          displayError('Failed to update tuple', error)
           reject(error)
         })
     })
@@ -122,9 +99,7 @@ class QueryService {
           resolve(subset)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to export query', error)
-          Vue.$toast.error(`[${code}] Failed to export query: ${message}`)
+          displayError('Failed to export subset', error)
           reject(error)
         })
     })
@@ -139,9 +114,7 @@ class QueryService {
           resolve(metadata)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to export metadata', error)
-          Vue.$toast.error(`[${code}] Failed to export metadata: ${message}`)
+          displayError('Failed to export metadata', error)
           reject(error)
         })
     })
@@ -156,9 +129,7 @@ class QueryService {
           resolve(result)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to execute statement', error)
-          Vue.$toast.error(`[${code}] Failed to execute statement: ${message}`)
+          displayError('Failed to execute query', error)
           reject(error)
         })
     })
@@ -173,9 +144,7 @@ class QueryService {
           resolve(result)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to re-execute query', error)
-          Vue.$toast.error(`[${code}] Failed to re-execute query: ${message}`)
+          displayError('Failed to re-execute query', error)
           reject(error)
         })
     })
@@ -190,9 +159,7 @@ class QueryService {
           resolve(count)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to re-execute query count', error)
-          Vue.$toast.error(`[${code}] Failed to re-execute query count: ${message}`)
+          displayError('Failed to re-execute query and count results', error)
           reject(error)
         })
     })
@@ -207,9 +174,7 @@ class QueryService {
           resolve(result)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to re-execute view', error)
-          Vue.$toast.error(`[${code}] Failed to re-execute view: ${message}`)
+          displayError('Failed to re-execute view', error)
           reject(error)
         })
     })
@@ -224,9 +189,7 @@ class QueryService {
           resolve(count)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to re-execute view count', error)
-          Vue.$toast.error(`[${code}] Failed to re-execute view count: ${message}`)
+          displayError('Failed to re-execute view and count results', error)
           reject(error)
         })
     })
@@ -241,9 +204,7 @@ class QueryService {
           resolve(view)
         })
         .catch((error) => {
-          const { code, message } = error.response.data
-          console.error('Failed to find view', error)
-          Vue.$toast.error(`[${code}] Failed to find view: ${message}`)
+          displayError('Failed to find view', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/search.service.js b/dbrepo-ui/api/search.service.js
index c037199f36..b30c79b6fe 100644
--- a/dbrepo-ui/api/search.service.js
+++ b/dbrepo-ui/api/search.service.js
@@ -1,19 +1,16 @@
-import Vue from 'vue'
-import axios from 'axios'
+import api, { displayError } from '@/api/index'
 
 class SearchService {
   getFields (type) {
     return new Promise((resolve, reject) => {
-      axios.get(`/api/search/${type}/fields`, { headers: { Accept: 'application/json' } })
+      api.get(`/api/search/${type}/fields`, { headers: { Accept: 'application/json' } })
         .then((response) => {
           const json = response.data
           console.debug('fields result', json)
           resolve(json)
         })
         .catch((error) => {
-          const { code, message } = error
-          console.error(`Failed to load ${type} fields`, error)
-          Vue.$toast.error(`[${code}] Failed to load ${type} fields: ${message}`)
+          displayError('Failed to load fields', error)
           reject(error)
         })
     })
@@ -36,16 +33,14 @@ class SearchService {
       field_value_pairs: { ...localSearchData }
     }
     return new Promise((resolve, reject) => {
-      axios.post(`/api/search${index ? `/${index}` : ''}`, payload, { headers: { Accept: 'application/json' } })
+      api.post(`/api/search${index ? `/${index}` : ''}`, payload, { headers: { Accept: 'application/json' } })
         .then((response) => {
           const { hits } = response.data
           console.debug('advanced search response', hits.hits)
           resolve(hits.hits)
         })
         .catch((error) => {
-          const { code, message } = error
-          console.error('Failed to load search results', error)
-          Vue.$toast.error(`[${code}] Failed to load search results: ${message}`)
+          displayError('Failed to load search results', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/semantic.service.js b/dbrepo-ui/api/semantic.service.js
index 662106eb54..0935727a57 100644
--- a/dbrepo-ui/api/semantic.service.js
+++ b/dbrepo-ui/api/semantic.service.js
@@ -10,7 +10,7 @@ class SemanticService {
           resolve(ontologies)
         })
         .catch((error) => {
-          displayError(error, 'Failed to load ontologies')
+          displayError('Failed to load ontologies', error)
           reject(error)
         })
     })
@@ -25,7 +25,7 @@ class SemanticService {
           resolve(concepts)
         })
         .catch((error) => {
-          displayError(error, 'Failed to load concepts')
+          displayError('Failed to load concepts', error)
           reject(error)
         })
     })
@@ -40,7 +40,7 @@ class SemanticService {
           resolve(concept)
         })
         .catch((error) => {
-          displayError(error, 'Failed to update concept')
+          displayError('Failed to update concept', error)
           reject(error)
         })
     })
@@ -55,7 +55,7 @@ class SemanticService {
           resolve(units)
         })
         .catch((error) => {
-          displayError(error, 'Failed to load units')
+          displayError('Failed to load units', error)
           reject(error)
         })
     })
@@ -70,7 +70,7 @@ class SemanticService {
           resolve(unit)
         })
         .catch((error) => {
-          displayError(error, 'Failed to update unit')
+          displayError('Failed to update unit', error)
           reject(error)
         })
     })
@@ -85,7 +85,7 @@ class SemanticService {
           resolve(ontology)
         })
         .catch((error) => {
-          displayError(error, 'Failed to find ontology')
+          displayError('Failed to find ontology', error)
           reject(error)
         })
     })
@@ -100,7 +100,7 @@ class SemanticService {
           resolve(ontology)
         })
         .catch((error) => {
-          displayError(error, 'Failed to register ontology')
+          displayError('Failed to register ontology', error)
           reject(error)
         })
     })
@@ -115,7 +115,7 @@ class SemanticService {
           resolve(ontology)
         })
         .catch((error) => {
-          displayError(error, 'Failed to update ontology')
+          displayError('Failed to update ontology', error)
           reject(error)
         })
     })
@@ -126,7 +126,7 @@ class SemanticService {
       api.delete(`/api/semantic/ontology/${id}`, { headers: { Accept: 'application/json' } })
         .then(() => resolve())
         .catch((error) => {
-          displayError(error, 'Failed to unregister ontology')
+          displayError('Failed to unregister ontology', error)
           reject(error)
         })
     })
@@ -141,7 +141,7 @@ class SemanticService {
           resolve(semantics)
         })
         .catch((error) => {
-          displayError(error, 'Failed to suggest table column semantic')
+          displayError('Failed to suggest table column semantic', error)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/api/table.mapper.js b/dbrepo-ui/api/table.mapper.js
index 2f2c69c552..2150619bf4 100644
--- a/dbrepo-ui/api/table.mapper.js
+++ b/dbrepo-ui/api/table.mapper.js
@@ -39,6 +39,16 @@ class TableMapper {
       }
     })
   }
+
+  tableNameToInternalName (name) {
+    return name.toString()
+      .normalize('NFKD')
+      .toLowerCase()
+      .trim()
+      .replace(/\s+/g, '-')
+      .replace(/[^\w-]+/g, '')
+      .replace(/--+/g, '_')
+  }
 }
 
 export default new TableMapper()
diff --git a/dbrepo-ui/api/table.service.js b/dbrepo-ui/api/table.service.js
index d2ddf42b63..0b3c7d3d5a 100644
--- a/dbrepo-ui/api/table.service.js
+++ b/dbrepo-ui/api/table.service.js
@@ -41,6 +41,19 @@ class TableService {
     })
   }
 
+  findByName (databaseId, name) {
+    return new Promise((resolve, reject) => {
+      this.findAll(databaseId)
+        .then((tables) => {
+          const filter = tables.filter(t => t.name === name)
+          if (filter.length === 1) {
+            resolve(filter[0])
+          }
+          reject(new Error('Failed to find table with name ' + name + ' in database with id ' + databaseId))
+        })
+    })
+  }
+
   updateColumn (databaseId, tableId, columnId, data) {
     return new Promise((resolve, reject) => {
       api.put(`/api/database/${databaseId}/table/${tableId}/column/${columnId}`, data, { headers: { Accept: 'application/json' } })
@@ -164,6 +177,7 @@ class TableService {
     return new Promise((resolve, reject) => {
       api.delete(`/api/database/${databaseId}/table/${tableId}`, { headers: { Accept: 'application/json' } })
         .then(() => {
+          console.info('Deleted table with id', tableId)
           resolve()
         })
         .catch((error) => {
diff --git a/dbrepo-ui/components/TableSchema.vue b/dbrepo-ui/components/TableSchema.vue
index d2447f2e27..4714f76275 100644
--- a/dbrepo-ui/components/TableSchema.vue
+++ b/dbrepo-ui/components/TableSchema.vue
@@ -109,7 +109,7 @@
         <v-btn v-if="back" class="mt-10 mr-2 mb-1" @click="stepBack()">
           Back
         </v-btn>
-        <v-btn color="primary" :loading="localLoading" class="mt-10 mb-1" @click="submit">
+        <v-btn color="primary" :loading="loading" class="mt-10 mb-1" @click="submit">
           Continue
         </v-btn>
       </div>
@@ -134,23 +134,11 @@ export default {
       default () {
         return false
       }
-    },
-    error: {
-      type: Boolean,
-      default () {
-        return false
-      }
-    },
-    loading: {
-      type: Boolean,
-      default () {
-        return false
-      }
     }
   },
   data () {
     return {
-      localLoading: false,
+      loading: false,
       dateFormats: [],
       valid: true,
       finished: false,
@@ -163,13 +151,7 @@ export default {
       return this.columns.filter(c => c.primary_key).length === 0
     }
   },
-  watch: {
-    loading () {
-      this.localLoading = this.loading
-    }
-  },
   mounted () {
-    this.localLoading = this.loading
     this.loadDateFormats()
   },
   methods: {
@@ -194,12 +176,12 @@ export default {
         const database = await DatabaseService.findOne(this.$route.params.database_id)
         this.dateFormats = database.image.date_formats
       } finally {
-        this.localLoading = false
+        this.loading = false
       }
     },
     submit () {
       this.finished = true
-      this.localLoading = true
+      this.loading = true
       this.$emit('close', { success: true })
     },
     setOthers (column) {
diff --git a/dbrepo-ui/components/TableToolbar.vue b/dbrepo-ui/components/TableToolbar.vue
index c4ebefe8e1..90720a6ff2 100644
--- a/dbrepo-ui/components/TableToolbar.vue
+++ b/dbrepo-ui/components/TableToolbar.vue
@@ -53,7 +53,6 @@
     </v-dialog>
     <v-dialog
       v-model="dropTableDialog"
-      persistent
       max-width="640">
       <DropTable @close="closed" />
     </v-dialog>
diff --git a/dbrepo-ui/pages/database/_database_id/table/import.vue b/dbrepo-ui/pages/database/_database_id/table/import.vue
index a64bcc54f6..ad767f4315 100644
--- a/dbrepo-ui/pages/database/_database_id/table/import.vue
+++ b/dbrepo-ui/pages/database/_database_id/table/import.vue
@@ -183,7 +183,7 @@
         Table Schema
       </v-stepper-step>
       <v-stepper-content step="4">
-        <TableSchema :back="true" :error="error" :loading="loading" :columns="tableCreate.columns" @close="schemaClose" />
+        <TableSchema ref="schema" :back="true" :columns="tableCreate.columns" @close="schemaClose" />
       </v-stepper-content>
       <v-stepper-step
         :complete="step > 5"
@@ -251,7 +251,7 @@ export default {
         required: value => !!value || 'Required'
       },
       dateFormats: [],
-      tableNames: [],
+      tables: [],
       tableCreate: {
         name: null,
         description: null,
@@ -284,6 +284,9 @@ export default {
     roles () {
       return this.$store.state.roles
     },
+    database () {
+      return this.$store.state.database
+    },
     validTableName () {
       if (this.tableCreate.name === null) {
         return true
@@ -291,13 +294,13 @@ export default {
       if (this.tableCreate.name.length < 3) {
         return true
       }
-      return !this.tableNames.includes(this.tableCreate.name.toString()
-        .normalize('NFKD')
-        .toLowerCase()
-        .trim()
-        .replace(/\s+/g, '-')
-        .replace(/[^\w-]+/g, '')
-        .replace(/--+/g, '_'))
+      if (!this.database || !('tables' in this.database)) {
+        return false
+      }
+      return !this.database
+        .tables
+        .map(t => t.internal_name)
+        .includes(TableMapper.tableNameToInternalName(this.tableCreate.name))
     },
     canInsertTableData () {
       if (!this.roles) {
@@ -308,7 +311,6 @@ export default {
   },
   mounted () {
     this.loadDateFormats()
-    this.listTables()
   },
   methods: {
     notEmpty,
@@ -379,16 +381,6 @@ export default {
           this.loading = false
         })
     },
-    listTables () {
-      this.loading = true
-      TableService.findAll(this.$route.params.database_id)
-        .then((tables) => {
-          this.tableNames = tables.map(t => t.internal_name)
-        })
-        .finally(() => {
-          this.loading = false
-        })
-    },
     schemaClose (event) {
       console.debug('schema closed', event)
       if (!event.success) {
@@ -396,7 +388,7 @@ export default {
         return
       }
       this.validStep4 = true
-      this.createTable()
+      this.createEmptyTableAndImport()
     },
     async loadDateFormats () {
       this.loading = true
@@ -404,10 +396,10 @@ export default {
         const database = await DatabaseService.findOne(this.$route.params.database_id)
         this.dateFormats = database.container.image.date_formats
       } finally {
-        this.localLoading = false
+        this.loading = false
       }
     },
-    createTable () {
+    createEmptyTableAndImport () {
       /* make enum values to array */
       const validColumns = this.tableCreate.columns.map((column) => {
         // validate `id` column: must be a PK
@@ -420,6 +412,24 @@ export default {
       // bail out if there is a problem with one of the columns
       if (!validColumns.every(Boolean)) { return }
       const table = TableMapper.tableCreateToTableCreateDto(this.tableCreate)
+      // check if table already exists (e.g. due to previous fail to import)
+      TableService.findByName(this.$route.params.database_id, this.tableCreate.name)
+        .then((table) => {
+          console.warn('There exists already a table with name', this.tableCreate.name, 'in database: attempt to delete table with id', table.id)
+          TableService.delete(this.$route.params.database_id, table.id)
+            .then(() => {
+              this.$store.dispatch('reloadDatabase')
+            })
+        })
+        .catch(() => {
+          /* ignore, table does not (yet) exist */
+        })
+        .finally(() => {
+          // finally create the table and import csv
+          this.createTableAndImport(table)
+        })
+    },
+    createTableAndImport (table) {
       TableService.create(this.$route.params.database_id, table)
         .then((table) => {
           this.newTableId = table.id
@@ -429,11 +439,17 @@ export default {
               await this.$store.dispatch('reloadDatabase')
               this.step = 5
             })
+            .catch(() => {
+              this.$refs.schema.loading = false
+            })
             .finally(() => {
               this.loading = false
             })
         })
         .catch(() => {
+          this.$refs.schema.loading = false
+        })
+        .finally(() => {
           this.loading = false
         })
     }
-- 
GitLab