Keep getting Error: Cannot write headers after they are sent to the client
(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"}
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!
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 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!
👋 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.
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.