next-connect icon indicating copy to clipboard operation
next-connect copied to clipboard

Next Js App router catch-all error handler

Open thomasheimh opened this issue 1 year ago • 4 comments

How to use next connect catch-all error handler with app router?

interface RequestContext {
  params: { id: string }
}
const router = createEdgeRouter<NextRequest, RequestContext>()

where should I add the below to catch error

function onError(err, req, res) {
  logger.log(err);
  // OR: console.error(err);

  res.status(500).end("Internal server error");
}

thomasheimh avatar Jul 28 '23 04:07 thomasheimh

I am using a factory function that returns the NodeRouter object resulting from createRouter(). Each endpoint calls the factory and adds the endpoint specifics. The last call is the handler() which uses standard handlerOptions object as catch-all error handler.

nocodehummel avatar Aug 28 '23 07:08 nocodehummel

Could you please provide your example for this solution?

demirtasdurmus avatar Sep 12 '23 07:09 demirtasdurmus

How to use next connect catch-all error handler with app router?

interface RequestContext {
  params: { id: string }
}
const router = createEdgeRouter<NextRequest, RequestContext>()

where should I add the below to catch error

function onError(err, req, res) {
  logger.log(err);
  // OR: console.error(err);

  res.status(500).end("Internal server error");
}

Man, this worked for me: https://github.com/hoangvvo/next-connect/issues/202#issuecomment-1955765901

silvaezequias avatar Feb 21 '24 02:02 silvaezequias

I've used below (rough example) to catch unhandled errors in my app router / middleware. Might be useful for someone.

const initMiddleware = async (req, _, next) => {
  const start = Date.now();

  // for any unhandled errors in subsequent middlewares
  let _next;
  try {
      _next = await next();
  } catch (err) {
      // can log error here 
      // can change how errors are handled below to suit your preference
      if (err instanceof SomeSpecificError) {
        // handle and return response
      }
      if (err instanceof ZodError) {
       return NextResponse.json({ ok: false }, { status: 422 });
     }
      if (err instanceof Error) {
          return NextResponse.json({ ok: false }, { status: 500 });
      }
      return NextResponse.json({ ok: false }, { status: 500 });
  } finally {
      const end = Date.now();
      // can do whatever such as adding logs here
      console.log(`request took ${end - start}ms`)
  }

    return await _next;
}

export const router = createEdgeRouter()
  // ensure to set this as the first middleware otherwise errors
  // won't be caught in the ones before it
  .use(initMiddleware)
  .clone()

I saw the example below suggested somewhere but I've not been able to get it to work for me in the app router

export const createAppRouterWithErrorHandling = () => {
    const router = createEdgeRouter();
    const handler = router.handler.bind(router);

    router.handler = () =>
        handler({
            onError: function() {},
            onNoMatch: function() {}
        });
    return router;
};

DNoel26 avatar Mar 07 '24 12:03 DNoel26