diff --git a/pom.xml b/pom.xml
index ba64e7471da5692c9bd7ae6a0df35f6763e14d7c..2dfe0c5307f666131846c12188bdc2d4e876c3fb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,9 +3,9 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-starter-parent</artifactId>
-        <version>2.4.5</version>
+        <groupId>it.inaf.ia2</groupId>
+        <artifactId>vospace-parent</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
     <groupId>it.inaf.ia2</groupId>
@@ -18,61 +18,21 @@
         <finalName>${project.artifactId}-${project.version}</finalName>
         <!-- File catalog repository directory -->
         <init_database_scripts_path>../../../vospace-file-catalog</init_database_scripts_path>
-        <zonky.postgres-binaries.version>12.5.0</zonky.postgres-binaries.version>
     </properties>
 
     <dependencies>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-jdbc</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-devtools</artifactId>
-            <scope>runtime</scope>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
+            <groupId>it.inaf.ia2</groupId>
+            <artifactId>vospace-parent</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
         </dependency>
+        <!--
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-configuration-processor</artifactId>
             <optional>true</optional>
         </dependency>
-        <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>rap-client</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-             
-        <!-- Embedded PostgreSQL: -->
-        <dependency>
-            <groupId>com.opentable.components</groupId>
-            <artifactId>otj-pg-embedded</artifactId>
-            <version>0.13.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>it.oats.inaf</groupId>
-            <artifactId>vospace-datamodel</artifactId>
-            <version>1.0-SNAPSHOT</version>
-        </dependency>
-        
+        -->
         <dependency>
             <groupId>org.kamranzafar</groupId>
             <artifactId>jtar</artifactId>
@@ -80,49 +40,6 @@
         </dependency>
     </dependencies>
 
-    <profiles>
-        <profile>
-            <id>platform-linux</id>
-            <activation>
-                <os>
-                    <family>unix</family> 
-                </os>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>io.zonky.test.postgres</groupId>
-                    <artifactId>embedded-postgres-binaries-linux-amd64</artifactId>
-                    <version>${zonky.postgres-binaries.version}</version>
-                    <scope>test</scope>
-                </dependency>
-            </dependencies>
-        </profile>
-        <profile>
-            <id>platform-windows</id>
-            <activation>
-                <os>
-                    <family>windows</family>
-                </os>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>io.zonky.test.postgres</groupId>
-                    <artifactId>embedded-postgres-binaries-windows-amd64</artifactId>
-                    <version>${zonky.postgres-binaries.version}</version>
-                    <scope>test</scope>
-                </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
-
-    <repositories>
-        <repository>
-            <id>ia2-snapshots</id>
-            <name>your custom repo</name>
-            <url>http://repo.ia2.inaf.it/maven/repository/snapshots</url>
-        </repository>
-    </repositories>
-    
     <build>
         <finalName>${finalName}</finalName>
         <testResources>
@@ -144,14 +61,7 @@
                 </excludes>
             </testResource>
         </testResources>
-        <plugins>            
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.22.2</version>
-                <configuration>
-                    <trimStackTrace>false</trimStackTrace>
-                </configuration>
-            </plugin>
+        <plugins>
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
@@ -162,7 +72,6 @@
             <plugin>
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
-                <version>0.8.6</version>
                 <executions>
                     <execution>
                         <goals>
diff --git a/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java
index 637208277cf6e33451ecf75cc448c98dadb3e073..9a2a8732a4ae7695ac781fcf0642e311bd5692b5 100644
--- a/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java
+++ b/src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java
@@ -6,10 +6,10 @@
 package it.inaf.ia2.transfer.controller;
 
 import it.inaf.ia2.transfer.auth.TokenPrincipal;
-import it.inaf.ia2.transfer.exception.PermissionDeniedException;
 import it.inaf.ia2.transfer.service.ArchiveJob;
 import it.inaf.ia2.transfer.service.ArchiveJob.Type;
 import it.inaf.ia2.transfer.service.ArchiveService;
+import it.inaf.oats.vospace.exception.PermissionDeniedException;
 import java.io.File;
 import java.util.concurrent.CompletableFuture;
 import javax.servlet.http.HttpServletResponse;
diff --git a/src/main/java/it/inaf/ia2/transfer/controller/ErrorController.java b/src/main/java/it/inaf/ia2/transfer/controller/ErrorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..15ad520061e56b392fa2bb00f1c6407fc1288248
--- /dev/null
+++ b/src/main/java/it/inaf/ia2/transfer/controller/ErrorController.java
@@ -0,0 +1,20 @@
+/*
+ * This file is part of vospace-rest
+ * Copyright (C) 2021 Istituto Nazionale di Astrofisica
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.inaf.ia2.transfer.controller;
+
+import it.inaf.oats.vospace.exception.DefaultErrorController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.error.ErrorAttributes;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class ErrorController extends DefaultErrorController {
+
+    @Autowired
+    public ErrorController(ErrorAttributes errorAttributes) {
+        super(errorAttributes);
+    }
+}
diff --git a/src/main/java/it/inaf/ia2/transfer/controller/FileController.java b/src/main/java/it/inaf/ia2/transfer/controller/FileController.java
index 1ad60cb0ff63fcd66e3ec450c38ac4b682666906..8a049b69dc7b7044fd2874d6b158676957091eea 100644
--- a/src/main/java/it/inaf/ia2/transfer/controller/FileController.java
+++ b/src/main/java/it/inaf/ia2/transfer/controller/FileController.java
@@ -5,8 +5,9 @@
  */
 package it.inaf.ia2.transfer.controller;
 
-import it.inaf.ia2.transfer.exception.JobException;
 import it.inaf.ia2.transfer.persistence.JobDAO;
+import it.inaf.oats.vospace.exception.InternalFaultException;
+import it.inaf.oats.vospace.exception.VoSpaceErrorSummarizableException;
 import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -44,13 +45,12 @@ public abstract class FileController {
                 jobDAO.updateJobPhase(ExecutionPhase.COMPLETED, jobId);
             }
         } catch (Throwable t) {
-            JobException jobException;
-            if (t instanceof JobException) {
-                jobException = (JobException) t;
+            VoSpaceErrorSummarizableException jobException;
+            if (t instanceof VoSpaceErrorSummarizableException) {
+                jobException = (VoSpaceErrorSummarizableException) t;
             } else {
                 LOG.error("Unexpected error happened", t);
-                jobException = new JobException(JobException.Type.FATAL, "Internal Fault")
-                        .setErrorDetail("InternalFault: Unexpected error happened");
+                jobException = new InternalFaultException("Unexpected error happened");
             }
             if (jobId != null) {
                 jobDAO.setJobError(jobId, jobException);
diff --git a/src/main/java/it/inaf/ia2/transfer/controller/FileResponseUtil.java b/src/main/java/it/inaf/ia2/transfer/controller/FileResponseUtil.java
index 88a09952fee99bf7ef6ef4df61b1f400182308df..d56f5471ee83743b5c7f6cd70734951baec1378d 100644
--- a/src/main/java/it/inaf/ia2/transfer/controller/FileResponseUtil.java
+++ b/src/main/java/it/inaf/ia2/transfer/controller/FileResponseUtil.java
@@ -5,8 +5,8 @@
  */
 package it.inaf.ia2.transfer.controller;
 
-import it.inaf.ia2.transfer.exception.FileNotFoundException;
-import it.inaf.ia2.transfer.exception.JobException;
+import it.inaf.oats.vospace.exception.InternalFaultException;
+import it.inaf.oats.vospace.exception.NodeNotFoundException;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -33,13 +33,12 @@ public class FileResponseUtil {
 
         if (!file.exists()) {
             LOG.error("File not found: " + file.getAbsolutePath());
-            throw new FileNotFoundException(vosPath == null ? file.getAbsolutePath() : vosPath);
+            throw new NodeNotFoundException(vosPath == null ? file.getAbsolutePath() : vosPath);
         }
 
         if (!file.canRead()) {
             LOG.error("File not readable: " + file.getAbsolutePath());
-            throw new JobException(JobException.Type.FATAL, "Internal Fault")
-                    .setErrorDetail("InternalFault: File " + file.getName() + " is not readable");
+            throw new InternalFaultException("File " + file.getName() + " is not readable");
         }
 
         response.setHeader("Content-Disposition", "attachment; filename="
diff --git a/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java
index bc8cbd1b406221db81ad0eb1e288f873cf752147..a0b06a1a329c1489123be8bbf47fcf83bf3fdc38 100644
--- a/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java
+++ b/src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java
@@ -7,12 +7,12 @@ package it.inaf.ia2.transfer.controller;
 
 import it.inaf.ia2.transfer.persistence.model.FileInfo;
 import it.inaf.ia2.transfer.auth.TokenPrincipal;
-import it.inaf.ia2.transfer.exception.FileNotFoundException;
-import it.inaf.ia2.transfer.exception.InvalidArgumentException;
-import it.inaf.ia2.transfer.exception.PermissionDeniedException;
 import it.inaf.ia2.transfer.persistence.FileDAO;
 import it.inaf.ia2.transfer.persistence.JobDAO;
 import it.inaf.ia2.transfer.service.AuthorizationService;
+import it.inaf.oats.vospace.exception.InvalidArgumentException;
+import it.inaf.oats.vospace.exception.NodeNotFoundException;
+import it.inaf.oats.vospace.exception.PermissionDeniedException;
 import java.io.File;
 import java.util.Optional;
 import javax.servlet.http.HttpServletResponse;
@@ -65,13 +65,13 @@ public class GetFileController extends FileController {
                 FileInfo fileInfo = optFileInfo.get();
 
                 if (!authorizationService.isDownloadable(fileInfo, (TokenPrincipal) request.getUserPrincipal())) {
-                    throw new PermissionDeniedException("PermissionDenied Path: " + path);
+                    throw PermissionDeniedException.forPath(path);
                 }
 
                 File file = new File(fileInfo.getOsPath());
                 FileResponseUtil.getFileResponse(response, file, path);
             } else {
-                throw new FileNotFoundException(path);
+                throw new NodeNotFoundException(path);
             }
         }, jobId);
     }
diff --git a/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java b/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java
index 3b6578a138b5c3eea2e6ed72abc3bda9196b6187..e218777720bbb8c99af40ddad9b9d552f316567a 100644
--- a/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java
+++ b/src/main/java/it/inaf/ia2/transfer/controller/PutFileController.java
@@ -5,12 +5,12 @@
  */
 package it.inaf.ia2.transfer.controller;
 
-import it.inaf.ia2.transfer.exception.FileNotFoundException;
-import it.inaf.ia2.transfer.exception.InsufficientStorageException;
-import it.inaf.ia2.transfer.exception.InvalidArgumentException;
 import it.inaf.ia2.transfer.persistence.model.FileInfo;
 import it.inaf.ia2.transfer.persistence.FileDAO;
 import it.inaf.ia2.transfer.persistence.JobDAO;
+import it.inaf.oats.vospace.exception.InvalidArgumentException;
+import it.inaf.oats.vospace.exception.NodeNotFoundException;
+import it.inaf.oats.vospace.exception.QuotaExceededException;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -73,7 +73,7 @@ public class PutFileController extends FileController {
                 // if MultipartFile provides file size it is possible to check
                 // quota limit before reading the stream
                 if (remainingQuota != null && file != null && file.getSize() > remainingQuota) {
-                    throw new InsufficientStorageException("QuotaExceeded Path: " + fileInfo.getVirtualPath());
+                    throw new QuotaExceededException("Path: " + fileInfo.getVirtualPath());
                 }
                 
                 if (file != null) {
@@ -87,7 +87,7 @@ public class PutFileController extends FileController {
                     throw new RuntimeException(ex);
                 }
             } else {
-                throw new FileNotFoundException(path);
+                throw new NodeNotFoundException(path);
             }
         }, jobId);
     }
@@ -127,7 +127,7 @@ public class PutFileController extends FileController {
             // Quota limit is checked again to handle cases where MultipartFile is not used
             if (remainingQuota != null && fileSize > remainingQuota) {
                 file.delete();
-                throw new InsufficientStorageException("QuotaExceeded Path: " + fileInfo.getVirtualPath());
+                throw new QuotaExceededException("Path: " + fileInfo.getVirtualPath());
             }
 
             String md5Checksum = makeMD5Checksum(file);
diff --git a/src/main/java/it/inaf/ia2/transfer/exception/ErrorController.java b/src/main/java/it/inaf/ia2/transfer/exception/ErrorController.java
deleted file mode 100644
index ed77cc8a5bf51906ae676c8b85ac4219b9aa8fa4..0000000000000000000000000000000000000000
--- a/src/main/java/it/inaf/ia2/transfer/exception/ErrorController.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of vospace-rest
- * Copyright (C) 2021 Istituto Nazionale di Astrofisica
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.inaf.ia2.transfer.exception;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
-import org.springframework.boot.web.error.ErrorAttributeOptions;
-import org.springframework.boot.web.servlet.error.ErrorAttributes;
-import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-@RequestMapping("${server.error.path:${error.path:/error}}")
-public class ErrorController extends AbstractErrorController {
-
-    @Autowired
-    public ErrorController(ErrorAttributes errorAttributes) {
-        super(errorAttributes);
-    }
-
-    @RequestMapping(produces = MediaType.TEXT_XML_VALUE)
-    public void errorText(HttpServletRequest request, HttpServletResponse response) throws Exception {
-        ErrorAttributeOptions options = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);
-        Map<String, Object> errors = super.getErrorAttributes(request, options);
-        response.setContentType("text/plain;charset=UTF-8");
-        response.setCharacterEncoding("UTF-8");
-        String errorMessage = (String) errors.get("message");
-        if (errorMessage != null) {
-            response.getOutputStream().write(errorMessage.getBytes(StandardCharsets.UTF_8));
-        }
-    }
-
-    @Override
-    public String getErrorPath() {
-        return null;
-    }
-}
diff --git a/src/main/java/it/inaf/ia2/transfer/exception/FileNotFoundException.java b/src/main/java/it/inaf/ia2/transfer/exception/FileNotFoundException.java
deleted file mode 100644
index 459a465a7bd6356b278c9bfbce10b423320ac367..0000000000000000000000000000000000000000
--- a/src/main/java/it/inaf/ia2/transfer/exception/FileNotFoundException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is part of vospace-file-service
- * Copyright (C) 2021 Istituto Nazionale di Astrofisica
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.inaf.ia2.transfer.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-@ResponseStatus(HttpStatus.NOT_FOUND)
-public class FileNotFoundException extends JobException {
-
-    public FileNotFoundException(String path) {
-        super(Type.FATAL, "Node Not Found");
-        setErrorDetail("NodeNotFound Path: " + path);
-    }
-}
diff --git a/src/main/java/it/inaf/ia2/transfer/exception/InsufficientStorageException.java b/src/main/java/it/inaf/ia2/transfer/exception/InsufficientStorageException.java
deleted file mode 100644
index 1dc59d6c226e6e9f747dcc3000536e00104e4d45..0000000000000000000000000000000000000000
--- a/src/main/java/it/inaf/ia2/transfer/exception/InsufficientStorageException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is part of vospace-file-service
- * Copyright (C) 2021 Istituto Nazionale di Astrofisica
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.inaf.ia2.transfer.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-@ResponseStatus(HttpStatus.INSUFFICIENT_STORAGE)
-public class InsufficientStorageException extends JobException {
-
-    public InsufficientStorageException(String errorDetail) {
-        super(Type.FATAL, "Quota Exceeded");
-        setErrorDetail(errorDetail);
-    }
-}
diff --git a/src/main/java/it/inaf/ia2/transfer/exception/InvalidArgumentException.java b/src/main/java/it/inaf/ia2/transfer/exception/InvalidArgumentException.java
deleted file mode 100644
index 6a7c97af6c8d00ab44913bf88db1ae0a184c0fb6..0000000000000000000000000000000000000000
--- a/src/main/java/it/inaf/ia2/transfer/exception/InvalidArgumentException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is part of vospace-file-service
- * Copyright (C) 2021 Istituto Nazionale di Astrofisica
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.inaf.ia2.transfer.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-@ResponseStatus(HttpStatus.BAD_REQUEST)
-public class InvalidArgumentException extends JobException {
-
-    public InvalidArgumentException(String message) {
-        super(Type.FATAL, "Invalid Argument");
-        setErrorDetail("InvalidArgument: " + message);
-    }
-}
diff --git a/src/main/java/it/inaf/ia2/transfer/exception/JobException.java b/src/main/java/it/inaf/ia2/transfer/exception/JobException.java
deleted file mode 100644
index cb8c4252400cbb7dda00c8d97adfff746aeb4eb7..0000000000000000000000000000000000000000
--- a/src/main/java/it/inaf/ia2/transfer/exception/JobException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This file is part of vospace-file-service
- * Copyright (C) 2021 Istituto Nazionale di Astrofisica
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.inaf.ia2.transfer.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-public class JobException extends RuntimeException {
-
-    public static enum Type {
-
-        TRANSIENT("transient"),
-        FATAL("fatal");
-
-        private final String value;
-
-        private Type(String v) {
-            value = v;
-        }
-
-        public String value() {
-            return value;
-        }
-    }
-
-    private final Type type;
-    private String errorDetail;
-
-    public JobException(Type type, String message) {
-        super(message);
-        this.type = type;
-    }
-
-    public Type getType() {
-        return type;
-    }
-
-    public String getErrorDetail() {
-        return errorDetail;
-    }
-
-    public final JobException setErrorDetail(String errorDetail) {
-        this.errorDetail = errorDetail;
-        return this;
-    }
-}
diff --git a/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java b/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java
deleted file mode 100644
index 6658bc8791a6e442c51229c075099b7fb53a2a6c..0000000000000000000000000000000000000000
--- a/src/main/java/it/inaf/ia2/transfer/exception/PermissionDeniedException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is part of vospace-file-service
- * Copyright (C) 2021 Istituto Nazionale di Astrofisica
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.inaf.ia2.transfer.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-@ResponseStatus(value = HttpStatus.FORBIDDEN)
-public class PermissionDeniedException extends JobException {
-
-    public PermissionDeniedException(String errorDetail) {
-        super(Type.FATAL, "Permission Denied");
-        setErrorDetail(errorDetail);
-    }
-}
diff --git a/src/main/java/it/inaf/ia2/transfer/persistence/JobDAO.java b/src/main/java/it/inaf/ia2/transfer/persistence/JobDAO.java
index e964ba38c51522ec64c2d9f0390abf1ee9a04e57..b75c555282da071dc3fa1b8234fae3ad6e7c9e99 100644
--- a/src/main/java/it/inaf/ia2/transfer/persistence/JobDAO.java
+++ b/src/main/java/it/inaf/ia2/transfer/persistence/JobDAO.java
@@ -5,7 +5,7 @@
  */
 package it.inaf.ia2.transfer.persistence;
 
-import it.inaf.ia2.transfer.exception.JobException;
+import it.inaf.oats.vospace.exception.VoSpaceErrorSummarizableException;
 import java.sql.Types;
 import javax.sql.DataSource;
 import net.ivoa.xml.uws.v1.ExecutionPhase;
@@ -64,7 +64,7 @@ public class JobDAO {
         return result;
     }
 
-    public void setJobError(String jobId, JobException jobError) {
+    public void setJobError(String jobId, VoSpaceErrorSummarizableException jobError) {
 
         String sql = "UPDATE job SET phase = ?, error_message = ?, error_type = ?,\n"
                 + "error_has_detail = ?, error_detail = ?, end_time = NOW()\n"
@@ -74,9 +74,9 @@ public class JobDAO {
             int i = 0;
             ps.setObject(++i, ExecutionPhase.ERROR, Types.OTHER);
             ps.setString(++i, jobError.getMessage());
-            ps.setObject(++i, jobError.getType().value(), Types.OTHER);
-            ps.setBoolean(++i, jobError.getErrorDetail() != null);
-            ps.setString(++i, jobError.getErrorDetail());
+            ps.setObject(++i, jobError.getFault().getType().value(), Types.OTHER);
+            ps.setBoolean(++i, jobError.getDetailMessage() != null);
+            ps.setString(++i, jobError.getDetailMessage());
             ps.setString(++i, jobId);
         });
     }
diff --git a/src/main/java/it/inaf/ia2/transfer/service/ArchiveService.java b/src/main/java/it/inaf/ia2/transfer/service/ArchiveService.java
index 71b24946cd3ca3bdbd2612389a91d382d96c0788..74a1fd107c04a45dabad2a7e592ada0b3376a4ca 100644
--- a/src/main/java/it/inaf/ia2/transfer/service/ArchiveService.java
+++ b/src/main/java/it/inaf/ia2/transfer/service/ArchiveService.java
@@ -6,13 +6,13 @@
 package it.inaf.ia2.transfer.service;
 
 import it.inaf.ia2.transfer.auth.TokenPrincipal;
-import it.inaf.ia2.transfer.exception.InsufficientStorageException;
-import it.inaf.ia2.transfer.exception.JobException;
-import it.inaf.ia2.transfer.exception.JobException.Type;
 import it.inaf.ia2.transfer.persistence.FileDAO;
 import it.inaf.ia2.transfer.persistence.JobDAO;
 import it.inaf.ia2.transfer.persistence.LocationDAO;
 import it.inaf.ia2.transfer.persistence.model.FileInfo;
+import it.inaf.oats.vospace.exception.InternalFaultException;
+import it.inaf.oats.vospace.exception.PermissionDeniedException;
+import it.inaf.oats.vospace.exception.QuotaExceededException;
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -140,8 +140,7 @@ public class ArchiveService {
         if (!parentDir.exists()) {
             if (!parentDir.mkdirs()) {
                 LOG.error("Unable to create directory " + parentDir.getAbsolutePath());
-                throw new JobException(Type.FATAL, "Internal Fault")
-                        .setErrorDetail("InternalFault: Unable to create temporary directory for job");
+                throw new InternalFaultException("Unable to create temporary directory for job");
             }
         }
 
@@ -151,8 +150,7 @@ public class ArchiveService {
 
         if (!archiveFile.createNewFile()) {
             LOG.error("Unable to create file " + archiveFile.getAbsolutePath());
-            throw new JobException(Type.FATAL, "Internal Fault")
-                    .setErrorDetail("InternalFault: Unable to create archive file");
+            throw new InternalFaultException("Unable to create archive file");
         }
 
         return archiveFile;
@@ -166,7 +164,7 @@ public class ArchiveService {
         long usedSpace = Files.walk(parentDir.toPath()).mapToLong(p -> p.toFile().length()).sum();
 
         if (usedSpace > generatedDirMaxSize.toBytes()) {
-            throw new InsufficientStorageException("Archive size limit exceeded.");
+            throw new QuotaExceededException("Archive size limit exceeded.");
         }
     }
 
@@ -278,8 +276,7 @@ public class ArchiveService {
 
         if (baseUrl == null) {
             LOG.error("Location URL not found for location " + fileInfo.getLocationId());
-            throw new JobException(Type.FATAL, "Internal Fault")
-                    .setErrorDetail("InternalFault: Unable to retrieve location of file " + fileInfo.getVirtualPath());
+            throw new InternalFaultException("Unable to retrieve location of file " + fileInfo.getVirtualPath());
         }
 
         String url = baseUrl + "/" + fileInfo.getVirtualName();
@@ -308,8 +305,7 @@ public class ArchiveService {
 
     private <O extends OutputStream, E> void writeFileIntoArchive(FileInfo fileInfo, String relPath, TokenPrincipal tokenPrincipal, ArchiveHandler<O, E> handler) throws IOException {
         if (!authorizationService.isDownloadable(fileInfo, tokenPrincipal)) {
-            throw new JobException(Type.FATAL, "Permission Denied")
-                    .setErrorDetail("PermissionDenied: " + fileInfo.getVirtualPath());
+            throw PermissionDeniedException.forPath(fileInfo.getVirtualPath());
         }
 
         File file = new File(fileInfo.getOsPath());
diff --git a/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java b/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java
index 5214787b24d049e19e1c92fb1118d8195060fa16..2f8f6272b55a953f8a0235e55a14262eaaf1ee40 100644
--- a/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java
+++ b/src/test/java/it/inaf/ia2/transfer/controller/GetFileControllerTest.java
@@ -8,9 +8,9 @@ package it.inaf.ia2.transfer.controller;
 import it.inaf.ia2.transfer.persistence.model.FileInfo;
 import it.inaf.ia2.aa.jwt.TokenParser;
 import it.inaf.ia2.transfer.auth.GmsClient;
-import it.inaf.ia2.transfer.exception.JobException;
 import it.inaf.ia2.transfer.persistence.FileDAO;
 import it.inaf.ia2.transfer.persistence.JobDAO;
+import it.inaf.oats.vospace.exception.VoSpaceErrorSummarizableException;
 import java.io.File;
 import java.util.Collections;
 import java.util.HashMap;
@@ -226,9 +226,9 @@ public class GetFileControllerTest {
                     .andDo(print())
                     .andReturn().getResolvedException();
 
-            assertTrue(ex instanceof JobException);
-            JobException jobEx = (JobException) ex;
-            assertTrue(jobEx.getErrorDetail().contains("not readable"), jobEx.getErrorDetail());
+            assertTrue(ex instanceof VoSpaceErrorSummarizableException);
+            VoSpaceErrorSummarizableException jobEx = (VoSpaceErrorSummarizableException) ex;
+            assertTrue(jobEx.getDetailMessage().contains("not readable"), jobEx.getDetailMessage());
         } catch (Throwable t) {
             throw t;
         } finally {
diff --git a/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java b/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java
index 72f820bc328b5cacce5e71b70620b3be5c260891..7c29b107bf69b5d13308f188f9ee7f18c0f941b2 100644
--- a/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java
+++ b/src/test/java/it/inaf/ia2/transfer/controller/PutFileControllerTest.java
@@ -5,10 +5,10 @@
  */
 package it.inaf.ia2.transfer.controller;
 
-import it.inaf.ia2.transfer.exception.InsufficientStorageException;
 import it.inaf.ia2.transfer.persistence.model.FileInfo;
 import it.inaf.ia2.transfer.persistence.FileDAO;
 import it.inaf.ia2.transfer.persistence.JobDAO;
+import it.inaf.oats.vospace.exception.QuotaExceededException;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
@@ -251,7 +251,7 @@ public class PutFileControllerTest {
 
         verify(fileDao, times(1)).getRemainingQuota(eq("/path/to"));
 
-        assertTrue(ex instanceof InsufficientStorageException);
+        assertTrue(ex instanceof QuotaExceededException);
     }
 
     @Test
@@ -284,7 +284,7 @@ public class PutFileControllerTest {
 
         verify(fileDao, times(1)).getRemainingQuota(eq("/path/to"));
 
-        assertTrue(ex instanceof InsufficientStorageException);
+        assertTrue(ex instanceof QuotaExceededException);
     }
 
     private FileInfo createBaseFileInfo() {
diff --git a/src/test/java/it/inaf/ia2/transfer/persistence/JobDAOTest.java b/src/test/java/it/inaf/ia2/transfer/persistence/JobDAOTest.java
index 155cfaa180d9f1ee9b787472119281198a9f1c82..483302aaff7aad21755076edc7874b118de32673 100644
--- a/src/test/java/it/inaf/ia2/transfer/persistence/JobDAOTest.java
+++ b/src/test/java/it/inaf/ia2/transfer/persistence/JobDAOTest.java
@@ -5,8 +5,7 @@
  */
 package it.inaf.ia2.transfer.persistence;
 
-import it.inaf.ia2.transfer.exception.JobException;
-import it.inaf.ia2.transfer.exception.JobException.Type;
+import it.inaf.oats.vospace.exception.InternalFaultException;
 import javax.sql.DataSource;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -52,8 +51,7 @@ public class JobDAOTest {
 
         assertEquals(ExecutionPhase.QUEUED, dao.getJobPhase("pippo3"));
 
-        JobException jobError = new JobException(Type.FATAL, "Error message")
-                .setErrorDetail("Error detail");
+        InternalFaultException jobError = new InternalFaultException("Error detail");
 
         dao.setJobError("pippo3", jobError);
 
diff --git a/src/test/java/it/inaf/ia2/transfer/service/ArchiveServiceTest.java b/src/test/java/it/inaf/ia2/transfer/service/ArchiveServiceTest.java
index ae150bf4a0e020b60feb430dafa2db8a5cbc1b29..30c380ff36cb94c4ef7f29c8dc81024c50b9c66a 100644
--- a/src/test/java/it/inaf/ia2/transfer/service/ArchiveServiceTest.java
+++ b/src/test/java/it/inaf/ia2/transfer/service/ArchiveServiceTest.java
@@ -6,11 +6,11 @@
 package it.inaf.ia2.transfer.service;
 
 import it.inaf.ia2.transfer.auth.TokenPrincipal;
-import it.inaf.ia2.transfer.exception.InsufficientStorageException;
 import it.inaf.ia2.transfer.persistence.FileDAO;
 import it.inaf.ia2.transfer.persistence.JobDAO;
 import it.inaf.ia2.transfer.persistence.LocationDAO;
 import it.inaf.ia2.transfer.persistence.model.FileInfo;
+import it.inaf.oats.vospace.exception.QuotaExceededException;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -151,7 +151,7 @@ public class ArchiveServiceTest {
             fos.write(junk);
         }
 
-        Assertions.assertThrows(InsufficientStorageException.class, () -> {
+        Assertions.assertThrows(QuotaExceededException.class, () -> {
             archiveService.createArchive(job);
         });
     }