bolt-js icon indicating copy to clipboard operation
bolt-js copied to clipboard

Keep getting Error: Cannot write headers after they are sent to the client

Open mcarrf90-bz opened this issue 1 year ago • 4 comments

(Filling out the following with as much detail as you can provide will help us answer your question sooner.)

@slack/bolt ^3.17.1 version

Your App and Receiver Configuration

const receiver = new ExpressReceiver({...SLACK_CONFIG,  
  processEventErrorHandler,
  unhandledRequestHandler,
  logger});

const app = new App({
  ...SLACK_CONFIG,
  receiver,
  logger,
  logLevel: process.env.LOGGER_LEVEL as LogLevel || 'info' as LogLevel,
});


export async function processEventErrorHandler({ error, logger, request, response }) {
  const {body} = request
  if(body.event.type === 'user_change') logger.debug(`processEvent error: ${error}`);
  else logger.error(`processEvent error: ${error}`);
  // acknowledge it anyway!
  response.writeHead(200);
  response.end();
  return true;
}

export async function unhandledRequestHandler({ error, logger, request, response }) {
  logger.error(error);
  response.writeHead(200);
  response.end();
  return true;
}

Node.js runtime version

21.6.1

I keep getting Error: Cannot write headers after they are sent to the client on my production app, not really sure why. When I see the log that my unhandledRequestHandler there is no context at all:

{"level":50,"time":1716477134098,"pid":32,"hostname":"ip-10-0-28-28.sa-east-1.compute.internal"}

mcarrf90-bz avatar May 23 '24 15:05 mcarrf90-bz

Hey @mcarrf90-bz 👋 Thanks for the question and sharing this code snippet!

As I understand, only one HTTP response can be sent for each request, so only the first response is delivered here and following changes to the response headers won't be received by the client.

Instead of ending or returning a response in the first processEventErrorHandler is it possible to use Express.js middleware? This can allow various functions for handling requests in different ways and across different functions without requiring an immediate response!

I hope this is helpful and makes sense, but please let me know if that workaround might not work for you or if you have other questions!

zimeg avatar May 23 '24 15:05 zimeg

I implemented my error handlers as per the Bolt documentation: https://slack.dev/bolt-js/concepts#error-handling.

So in my particular case, not really sure how I could implement the express middleware. Something around the lines of:

app.error(async (req, res, next) =>
 // handle different error types
     next();
)

Not sure if this is a thing though

mcarrf90-bz avatar May 23 '24 16:05 mcarrf90-bz

@mcarrf90-bz apologies for letting this slip, but pretty much exactly that! Each app.listener can accept middleware that can do some processing before the next middleware which might be helpful for handling errors inline.

The link you shared is also great for error handling, especially at the app level with errors being throw. But once response.end() is called, that request can't be changed. If conditional checks are preferred for listeners, with custom responses for certain requests, I would recommend trying these checks as listener or even global middleware!

zimeg avatar May 30 '24 19:05 zimeg

👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.

github-actions[bot] avatar Jul 01 '24 00:07 github-actions[bot]

As this issue has been inactive for more than one month, we will be closing it. Thank you to all the participants! If you would like to raise a related issue, please create a new issue which includes your specific details and references this issue number.

github-actions[bot] avatar Jul 15 '24 00:07 github-actions[bot]