Skip to main content

Sending a Custom Response

Using the GENERAL_ERROR Status

Sometimes, you may want to send a custom error message from your API override to display to the user on the frontend. This can be done by sending the following JSON response from the API:

{
"status": "GENERAL_ERROR",
"message": "Some custom error message"
}

If you are using our pre-built ReactJS UI, the above response will render the mesage "Some custom error message" on the frontend UI. For custom UI, you can read this response and display the message in an error UI. This response can be returned from most of the APIs exposed by the backend SDK.

Let's take an example in which we want to prevent the user from signing up (via email / password) unless their email is preapproved by the app's admin. For this, we will override the sign up API to check if the input email is approved or not, and if not, we prevent the sign up, and send a custom error message.

import EmailPassword from "supertokens-node/recipe/emailpassword";

EmailPassword.init({
override: {
apis: (oI) => {
return {
...oI,
signUpPOST: async function (input) {
let email = input.formFields.find(i => i.id === "email")!.value as string;

if (emailNotAllowed(email)) {
return {
status: "GENERAL_ERROR",
message: "You are not allowed to sign up. Please contact the app's admin to get permission"
}
}
return oI.signUpPOST!(input);
}
}
}
}
})

function emailNotAllowed(email: string) {
// TODO: your impl to check if email is allowed or not
return true;
}

By Throwing an Error and Catching it

This method is useful in case you want to send a custom response from an overrided function which doesn't have access to the response object. This can happen in case you are overriding any of our recipe interface functions.

Let's take an example in which we want to prevent a user from logging into a new device if a session already exists for them in another device. We also want to send a custom response from the API in case we are preventing a login. For this, we will be overriding the createNewSession function from the Session recipe.

In the override, we will check if a session already exists for the given userId, and if it does, we will throw an error from the function. This error will be propogated to your application's error handler (or an error handler callback if you have provided one to us), in which you can catch this and send a custom response.

Step 1

First, we override the createNewSession function and throw an error in case a session already exists for a user. We can do this in the Session.init function:

import Session from "supertokens-node/recipe/session";

Session.init({
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
createNewSession: async function (input) {
const existingSessions = await Session.getAllSessionHandlesForUser(input.userId);
if (existingSessions.length > 0) {
// this means that the user already has a session on some other device
throw new Error("Session already exists on another device");
}

// no other session exists, and so we can continue with logging in this user
return originalImplementation.createNewSession(input);
}
}
}
}
})

Step 2

Next, we want to catch the thrown error and then send a custom response to the client

import express from "express";

let app = express();

//...

// in your app's error handler, we catch the custom error
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
if (err.message === "Session already exists on another device") {
// TODO: send a custom response using res
return;
}
res.send(500).send(err.message)
})