fastify/help

Help with "Fastify error: Reply was already sent, did you forget to return reply"

Besufikad17 opened this issue · 4 comments

How can I fix "Fastify error: Reply was already sent" error

Hey there guys, I am using fastify with drizzle-orm and In some of my routes I am getting "Fastify error: Reply was already sent, did you forget to return reply" even though I have used return for every res.send() call (like the code provided below). Am I missing something? Thanks in advance.

export const httpMethodValidatorMiddleware = (req:FastifyRequest, res:FastifyReply, method: string) => {
    if(req.method !== method)
        return res.status(StatusCode.METHOD_NOT_ALLOWED).send({message: "Method Not Allowed"})
}

const fastify = Fastify({
    logger: true
}).withTypeProvider<TypeBoxTypeProvider>()

const LoggerError = (data:any) => fastify.log.error(data)

export const completeCourse = async (req: FastifyRequest, res: FastifyReply) => {
  const method = httpMethodValidatorMiddleware(req, res, "PUT");

  if (method) return method;

  const { id } = req.user as Customer;

  if (!id) {
    return res.status(StatusCode.UNAUTHORIZED).send({
      message: "Unauthorized",
    });
  }

  try {
    const { language_enrollment_id, course_id } = req.body as typeof completeCourseBodySchema;
    const languageEnrollment = await getLanguageEnrollmentById(language_enrollment_id);

    if (languageEnrollment[0].customer_id != id) {
      return res
        .status(StatusCode.BAD_REQUEST)
        .send({ message: "Please enroll first!!" });
    }

    await updateLanguageEnrollment(language_enrollment_id, {
      language_level_id: languageEnrollment[0].language_level_id,
      customer_id: languageEnrollment[0].customer_id,
      reason: languageEnrollment[0].reason!,
      completed_courses: languageEnrollment[0].completed_courses! + 1,
      completed_sections: languageEnrollment[0].completed_sections!,
      current_course_id: course_id,
      current_section_id: languageEnrollment[0].current_section_id!
    });

    return res
      .code(StatusCode.ACCEPTED)
      .send({ message: "Course completed", data: languageEnrollment });
  } catch (error) {
    LoggerError(error);
    res
      .status(StatusCode.INTERNAL_SERVER_ERROR)
      .send({ message: "Internal Server Error", error: error });
  }
}

My Environment

  • node version: 20
  • fastify version: >=4.62.1
  • os: Linux

Thanks for reporting!

Can you provide steps to reproduce? We often need a reproducible example, e.g. some code that allows someone else to recreate your problem by just copying and pasting it. If it involves more than a couple of different file, create a new repository on GitHub and add a link to that.

Thanks for reporting!

Can you provide steps to reproduce? We often need a reproducible example, e.g. some code that allows someone else to recreate your problem by just copying and pasting it. If it involves more than a couple of different file, create a new repository on GitHub and add a link to that.

Sure

  import fastify from 'fastify'
  import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
  
  const getMessage = async(name: string) => {
        if(name == "") {
             throw Error("Please provide name");
        }
        return await `Hello, ${name}`;
  }
  
  const start = async() {
      try {
          const server = fastify({
              logger: true
          }).withTypeProvider<TypeBoxTypeProvider>();

        server.get('/', async (request, reply) => {
               try {
                    const message = await getMessage();
                    return res.status(200).send(message);
               } catch(error) {
                    return res.status(500).send(error);
                }
         });
      
        await server.listen({ port: 3000 });
     } catch (error) {
        console.error(error)
        process.exit(1)
      }
 }
 
 start()

Do not forget to return reply when calling reply.send explicitly

Hey guys, the issue was I used HookDoneCallbackFunction (done()) in my preHandler function, and it works after I removed it, Thanks a lot.