Why we need this?
Having good error handling is key to ensuring the robustness, correctness, and performance of the given application. Building robust applications requires you to throw and handle exceptions which occur during the runtime of the application. Thus, you will be introduced to the basic concepts of exception handling in Node.js as well as specific techniques for the CAP Service SDK for Node.js.
Error Handling and Error Types
Guidelines
"Let it crash" is a philosophy taken from the Erlang programming language (Joe Armstrong), which is also (partially) applicable to Node.js.
The key takeaways for programming errors are:
- Fail loudly: Do not hide errors and continue silently. Ensure to log unexpected errors correctly. Don't catch errors you can't handle.
- Don't develop in a defensive fashion: Focus on your business logic and only handle errors when you know they will occur. Use
try/catch
blocks only when necessary.
Never try to catch and handle unexpected errors, rejections of promises, and so on. If it is unexpected, you cannot handle it correctly. If you could, it would be expected (and should already be handled). Even if your apps should be stateless, you can never be 100% sure that a shared resource was not affected by the unexpected error. Therefore, you should never allow an app to continue running after such an event, especially for multi-tenant apps where there is a risk of information disclosure.
Following these guidelines will make your code shorter, clearer, and simpler.
Never Hide the Causes of Errors
When an error occurs, it should be possible to know the root cause. The CAP SDK for Node.js also throws exceptions, for example when a CRUD operation violates the foreign key constraints. In this case, the framework throws the exception UNIQUE_CONSTRAINT_VIOLATION. The problem in this case is that the end user will only see a cryptic error message:

It is therefore useful to provide a meaningful error message.
For this purpose, you can register an error handler in your service implementation, as exemplified in the editor below:
Example code:
// Imports
constcds=require("@sap/cds");
/**
* The service implementation with all service handlers
*/
module.exports=cds.service.impl(asyncfunction(){
/**
* Custom error handler
*
* throw a new error with: throw new Error('something bad happened');
*
**/
this.on("error",(err,req)=>{
switch(err.message){
case"UNIQUE_CONSTRAINT_VIOLATION":
err.message="The entry already exists.";
break;
default:
err.message=
"An error occured. Please retry. Technical error message: "+
err.message;
break;
}
});
});
This handler now steps in whenever this exception gets triggered and overrides it with an alternative error message:

Raising and Catching Exceptions
You will certainly add your implementations to your services. It is very likely, that you want to interrupt some operations before something crashes. In this case, you can throw a Node.js exception. Our recommendation is to look at the Node.js documentation for error handling.
Request Response
You can also use the req.error()
method to collect messages or errors and return them to the caller in the request-response. Read more here .
this.on("submitOrder",async(req)=>{
const{ book, amount }=req.data;
let{ stock }=awaitdb.read(Books,book,(b)=>b.stock);
if(stock >= amount){
awaitdb.update(Books,book).with({stock: (stock-=amount)});
awaitthis.emit("OrderedBook",{ book, amount,buyer: req.user.id});
returnreq.reply({ stock });// <-- Normal reply
}else{
// Reply with error code 409 and a custom error message
returnreq.error(409,`${amount} exceeds stock for book #${book}`);
}
});
Summary
The core error handling concepts in the CAP SDK for Node.js are now familiar to you. We strongly recommend incorporating these concepts to ensure the overall robustness of your CAP application.