Error Handling In App Router
Answered
Great Auk posted this in #help-forum
Great AukOP
Hi, I'm new to using NextJS' App Directory. How should I handle my API Route errors? Right now I'm using Zod on the backend and I'm getting an error that is messing with me. Can someone help?
Answered by andweas
What I do is reduce the “error†array thrown by Zod and just return that. Not sure if that’s the best move but that’s what I do if I want to return an error
try {
await GroupModel.parseAsync(req.body);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
return res.status(400).json(
error.issues.reduce((e: ZodError) => {
return e;
})
);
}25 Replies
Great AukOP
What I used to do was create my own router endpoint function and use it to handle errors, but now I guess I use:
export async function POST(req: NextApiRequest, res: NextApiResponse) {But I get an error (as I should) when parsing my body like this:
const body = await req.json();
const { email, name, password } = registerUserSchema.parse(body);I basically want to convert the thrown error (from zod) into:
res.status(err.code).json({ message: err.message })Any thoughts?
What I do is reduce the “error†array thrown by Zod and just return that. Not sure if that’s the best move but that’s what I do if I want to return an error
try {
await GroupModel.parseAsync(req.body);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
return res.status(400).json(
error.issues.reduce((e: ZodError) => {
return e;
})
);
}Answer
Great AukOP
Alright awesome, thank you
no problem 

that is the pages/api syntax, you have to edit it a little bit for it to work in the app directory route handlers, but the overall idea (try/catch) is the same
@joulev that is the pages/api syntax, you have to edit it a little bit for it to work in the app directory route handlers, but the overall idea (try/catch) is the same
Great AukOP
but isn't that bad practice? like every single api route will need like tons of try/catches
could u not just catch every error for the route?
here's what i used to do:
import { NextApiHandler } from "next";
import { ZodError } from "zod";
import { HTTPError } from "./exceptions";
export type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
export function createEndpoint<Resource>(
methods: Partial<Record<Method, NextApiHandler<Resource>>>
): NextApiHandler<Resource | { message: string } | any> {
const supportedMethods = Object.keys(methods);
return async (req, res) => {
const handler = methods[(req.method || "GET") as Method];
if (!handler) {
return res.status(405).json({
message: `You must ${supportedMethods.join(
", "
)} to this endpoint!`,
});
}
try {
await handler(req, res);
} catch (err) {
if (err instanceof HTTPError) {
return res.status(err.code).json({ message: err.message });
}
if (err instanceof ZodError) {
const issues = err.issues.map((it) => {
return { information: it.message, fields: it.path };
});
return res.status(422).json({
message: `${issues[0].fields} ${issues[0].information}`,
issues,
});
}
if (err instanceof Error) {
res.status(500).json({
message: process.env.NODE_ENV
? err.message
: "Something went wrong.",
});
}
}
};
}then you'd just use that to create the API route
export const POST = createRouteHandler(async (req) => {})write your own
createRouteHandler based on the createEndpoint aboveGreat AukOP
ah right ok that's fine
also is there a new type for
NextApiHandler?(request: NextRequest, context: Context) => Promise<Response> | Responsethat is the type of route handlers
Great AukOP
So no response param anymore?
for the type
Context, see the documentation, you have to type it manuallyGreat AukOP
awesome
v helpful thank you