diff --git a/src/main/java/it/inaf/oats/vospace/ListNodeController.java b/src/main/java/it/inaf/oats/vospace/ListNodeController.java
index 2a7ce2cdb2b7ad273676eabe7661d19c506a026f..e35793314cbb9cd049420c2aefccabbc812efe98 100644
--- a/src/main/java/it/inaf/oats/vospace/ListNodeController.java
+++ b/src/main/java/it/inaf/oats/vospace/ListNodeController.java
@@ -1,5 +1,6 @@
 package it.inaf.oats.vospace;
 
+import it.inaf.oats.vospace.exception.NodeNotFoundException;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -21,6 +22,7 @@ public class ListNodeController extends BaseNodeController {
             produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_XML_VALUE})
     public ResponseEntity<Node> listNode(HttpServletRequest request) {
         String path = getPath();
-        return ResponseEntity.ok(nodeDAO.listNode(path));
+        return ResponseEntity.ok(nodeDAO.listNode(path)
+                .orElseThrow(() -> new NodeNotFoundException(path)));
     }
 }
diff --git a/src/main/java/it/inaf/oats/vospace/exception/ErrorController.java b/src/main/java/it/inaf/oats/vospace/exception/ErrorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e4143e9a543b830075e642e2d51f751b573c7a3
--- /dev/null
+++ b/src/main/java/it/inaf/oats/vospace/exception/ErrorController.java
@@ -0,0 +1,33 @@
+package it.inaf.oats.vospace.exception;
+
+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.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 {
+        Map<String, Object> errors = super.getErrorAttributes(request, true);
+        response.setContentType("text/plain;charset=UTF-8");
+        response.getOutputStream().print((String) errors.get("message"));
+    }
+
+    @Override
+    public String getErrorPath() {
+        return null;
+    }
+}
diff --git a/src/main/java/it/inaf/oats/vospace/exception/NodeNotFoundException.java b/src/main/java/it/inaf/oats/vospace/exception/NodeNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..b14f4c2a791b2caea3786f43e3fc75d5a889296e
--- /dev/null
+++ b/src/main/java/it/inaf/oats/vospace/exception/NodeNotFoundException.java
@@ -0,0 +1,12 @@
+package it.inaf.oats.vospace.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(value = HttpStatus.NOT_FOUND)
+public class NodeNotFoundException extends VoSpaceException {
+
+    public NodeNotFoundException(String path) {
+        super("NodeNotFound: " + path);
+    }
+}
diff --git a/src/main/java/it/inaf/oats/vospace/exception/VoSpaceException.java b/src/main/java/it/inaf/oats/vospace/exception/VoSpaceException.java
new file mode 100644
index 0000000000000000000000000000000000000000..7aa48be8ba38533fd88fcbecf771fdd0738d093e
--- /dev/null
+++ b/src/main/java/it/inaf/oats/vospace/exception/VoSpaceException.java
@@ -0,0 +1,8 @@
+package it.inaf.oats.vospace.exception;
+
+public class VoSpaceException extends RuntimeException {
+
+    public VoSpaceException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
index 3f9a2b374558612f46e686ce84b7034191d84828..a0eb6521267a124883a70706948a25faf77c8019 100644
--- a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
+++ b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java
@@ -5,6 +5,7 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.List;
+import java.util.Optional;
 import javax.sql.DataSource;
 import net.ivoa.xml.vospace.v2.ContainerNode;
 import net.ivoa.xml.vospace.v2.DataNode;
@@ -43,7 +44,7 @@ public class NodeDAO {
         return myNode;
     }
 
-    public Node listNode(String path) {
+    public Optional<Node> listNode(String path) {
 
         String sql = "SELECT os.vos_path, n.node_id, type, async_trans, owner_id, group_read, group_write, is_public, content_length, created_on, last_modified from node n\n"
                 + "JOIN node_vos_path os ON n.node_id = os.node_id\n"
@@ -59,6 +60,10 @@ public class NodeDAO {
             return getNodeFromResultSet(row);
         });
 
+        if(parentAndChildren.isEmpty()) {
+            return Optional.empty();
+        }
+        
         // Query returns parent as first node
         Node node = parentAndChildren.get(0);
         
@@ -70,7 +75,7 @@ public class NodeDAO {
             }
         }
 
-        return node;
+        return Optional.of(node);
     }
 
     private String getFirstLevelChildrenSelector(String path) {
diff --git a/src/test/java/it/inaf/oats/vospace/ListNodeControllerTest.java b/src/test/java/it/inaf/oats/vospace/ListNodeControllerTest.java
index f1aa0ba31a9989a0b7d7be670868d0156420902d..47988ca6b974c7c28c1c72e1ee9180b67c270d62 100644
--- a/src/test/java/it/inaf/oats/vospace/ListNodeControllerTest.java
+++ b/src/test/java/it/inaf/oats/vospace/ListNodeControllerTest.java
@@ -2,6 +2,7 @@ package it.inaf.oats.vospace;
 
 import static it.inaf.oats.vospace.VOSpaceXmlTestUtil.loadDocument;
 import it.inaf.oats.vospace.persistence.NodeDAO;
+import java.util.Optional;
 import net.ivoa.xml.vospace.v2.ContainerNode;
 import net.ivoa.xml.vospace.v2.DataNode;
 import net.ivoa.xml.vospace.v2.Node;
@@ -55,7 +56,7 @@ public class ListNodeControllerTest {
     @Test
     public void testNodeXml() throws Exception {
 
-        when(dao.listNode(eq("/mynode"))).thenReturn(getDataNode());
+        when(dao.listNode(eq("/mynode"))).thenReturn(Optional.of(getDataNode()));
 
         String xml = mockMvc.perform(get("/nodes/mynode")
                 .accept(MediaType.APPLICATION_XML))
@@ -70,11 +71,18 @@ public class ListNodeControllerTest {
         verify(dao, times(1)).listNode(eq("/mynode"));
     }
 
-    private Node getRootNode() {
+    @Test
+    public void testNodeNotFound() throws Exception {
+        mockMvc.perform(get("/nodes/mynode")
+                .accept(MediaType.APPLICATION_XML))
+                .andExpect(status().isNotFound());
+    }
+
+    private Optional<Node> getRootNode() {
         ContainerNode root = new ContainerNode();
         root.setUri(URI_PREFIX + "/");
         root.getNodes().add(getDataNode());
-        return root;
+        return Optional.of(root);
     }
 
     private Node getDataNode() {
diff --git a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
index d2bb275c5c01f7ead10a3244268fe30019694120..b0757235b8f8dad130246a5ba0f2b10ceb9e6a37 100644
--- a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
+++ b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java
@@ -27,7 +27,7 @@ public class NodeDAOTest {
 
     @Test
     public void testListNode() {
-        ContainerNode root = (ContainerNode) dao.listNode("/");
+        ContainerNode root = (ContainerNode) dao.listNode("/").get();
         assertEquals(4, root.getNodes().size());
     }
 }