When my login function encounters an error, such as when the email or password is missing, or when the student does not exist or their email is not verified, the response from the server is in HTML format instead of JSON. This HTML response includes an error message along with a stack trace, which is not suitable for consumption by frontend applications expecting JSON responses.
const asyncHandler = (requestHandler) => {
return (req,res,next) => {
Promise.resolve(requestHandler(req,res,next)).
catch((err)=>next(err))
}
}
export {asyncHandler}
the ApiError class to throw custom error messages
class ApiError extends Error{
constructor(
statusCode,
message = "Something went wrong",
errors = [],
stack = ""
){
super(message)
this.statusCode = statusCode
this.data = null,
this.message = message
this.success = false
this.errors = errors
if(stack){
this.stack = stack
}
else{
Error.captureStackTrace(this,this.constructor)
}
}
}
export {ApiError}
login function, it works fine but not when in error handling
const login = asyncHandler(async(req,res) => {
const {Email, Password} = req.body;
/*if(!Email){
throw new ApiError(400,"E-mail is required")
}
if(!Password){
throw new ApiError(400,"Password is required")
}*/
const result = await authSchema.validateAsync(req.body)
const StdLogin = await student.findOne({
Email
})
if(!StdLogin){
throw new ApiError(400, "Student does not exist")
}
if(!StdLogin.Isverified){
throw new ApiError(401, "Email is not verified");
}
const StdPassCheck = await StdLogin.isPasswordCorrect(Password)
if(!StdPassCheck){
return res.status(400).json({ error: "Password is incorrect" });
}
const tempStd = StdLogin._id
const {Accesstoken, Refreshtoken} = await generateAccessAndRefreshTokens(tempStd)
const loggedInStd = await student.findById(tempStd).select(-Password -Refreshtoken)
const options = {
httpOnly:true,
secure:true,
}
return res
.status(200)
.cookie("Accesstoken", Accesstoken, options)
.cookie("Refreshtoken", Refreshtoken, options)
.json(
new ApiResponse(
200,{
user:loggedInStd
}, "logged in"
)
)
})
RESPONSE I AM GETTING INCASE OF ERROR:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Error: Student does not exist<br> at file:///C:/parag/CollegeProject/e-Learning-Platform/backend/src/controllers/student.controller.js:133:15<br> at process.processTicksAndRejections (node:internal/process/task_queues:95:5)</pre>
</body>
</html>
I want the function to return error or json data incase of error
2
Answers
await
throws?If either
const result = await authSchema.validateAsync...
orawait student.findOne...
throws, the inline handler function throws and hence rejects its returned promise, which causesin
asyncHandler
to reject which is caught and handled inasyncHandler
by callingnext(err)
. In express at least,next(err)
invokes an in-built error handler that responds to the request with an HTML page formatted as described in the post.The issue is consistent with
next(err)
being called, which is consistent with one of theawait
statements throwing without being caught (before theAPIError
Error extension is even used in runtime code).TL;DR
Solutions could be to add
try/catch
statements aroundawait
statements that are capable of throwing and explicitly handle errors in a controlled manner, or by usingAPIError
to create a consumable response instead of callingnext(err)
withinasyncHandler
.Disclaimer: this answer has not reviewed the design or use of
APIError
in any way.When your app throw an Error, if you don’t have any middleware to handle and return a json following res object, nodejs will return a html.
You need a middleware like this:
In app.js or index.js
The result: