Next.js Discord

Discord Forum

Error Handling In App Router

Answered
Great Auk posted this in #help-forum
Open in Discord
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;
        })
      );
    }
View full answer

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 :_smile:
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
Great AukOP
ah right ok that's fine
also is there a new type for NextApiHandler?
(request: NextRequest, context: Context) => Promise<Response> | Response
that 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 manually
@Great Auk So no response param anymore?
see edit
Great AukOP
awesome
v helpful thank you