What's the best way to handle errors in Next.js API routes? Currently Next always redirects to my error pages (404/500), which in turn sends my Sentry error logging mad. Is there a way to prevent this? I feel like errors in API routes should just return a JSON message with status. I've tried to catch thrown errors and return the appropriate responses which work locally but in production it still redirects. Any ideas?
3 Answers
I create a custom error class
class ErrorHandler extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
// captureStackTrace returns a string that reperesents the location of that particular error in the call. gives us a stack that helps us to find the location of that error in the code. this will help us to find the exact error in our code.
Error.captureStackTrace(this, this.constructor);
}
}
Then to avoid writing try/catch block I write a custom function to handle async error:
const catchAsyncErrors = (func) => (req, res, next) =>
// passing a controller function
Promise.resolve(func(req, res, next)).catch(next);
Then a controller:
const getSingleItem = catchAsyncErrors(async (req, res, next) => {
// in express we had req.params
const item = await Item.findById(req.query.id);
if (!item) {
return next(new ErrorHandler("Item not found with this id", 404));
}
res.status(200).json({
success: true,
item,
});
});
Comments
If you are working for nextjs 13 app directory there are two way using fetch new Response and another using NextResponse. Video reference from codeCodegrepper
import { NextRequest, NextResponse } from "next/server";
try{
........
try code
.........
}catch(error){
catch (error) {
//Response given by fetch api where we have to stringify our object
// return new Response(JSON.stringify({ error: "could not fetch group by" }), { status: 500 });
//Here Nexjs simple our work by giving NextResponse
return NextResponse.json({ error: "Could not fetch group by" }, { status: 500 });
}
}
Comments
You can set the response with the res.status.
async function example(req, res) {
switch (req.method) {
case "GET":
try {
const { data } = await foo();
res.status(200).json({ ...data});
} catch (error) {
console.error(error);
res.status(error.requestResult.statusCode).send(error.message);
}
default:
res.status(405).end(); //Method Not Allowed
break;
}
}
export default example;