unhandledRejection: ResponseAborted error when using SSE and App Router #61972
-
SummaryI'm using server side events (SSE) in my route.ts module. It's working as expected upon first connection from a client, but when the client/browser refreshes or reconnects, the below error is seen on the server:
The new connection receives data as expected. It appears that the original connection is still open on the server resulting in this error. I'm not sure how (or if) there's a way to correct this, or whether it's a bug in Next.js itself. Since none of my modules are listed in the stack trace I'm leaning towards the latter. Sample code (/src/app/api/events/route.ts): export async function GET(req: NextRequest) {
const responseStream = new TransformStream();
const writer = responseStream.writable.getWriter();
const encoder = new TextEncoder();
// ... redacted code that periodically updates the message variable ...
const eventData = { message: `Received "${message}"` };
const responseMsg = `data: ${JSON.stringify(eventData)}\n\n`;
writer.write(encoder.encode(responseMsg));
return new Response(responseStream.readable, {
status: 200,
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
},
}); Additional informationNo response ExampleNo response |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 12 replies
-
Figured out a fix for this? |
Beta Was this translation helpful? Give feedback.
-
Hi! Thanks to this reply in another discussion I was able to solve this. You just need to add a listener to the request object like in the comment: export async function GET(req: NextRequest) {
const stream = new TransformStream();
const writer = stream.writable.getWriter();
const encoder = new TextEncoder();
req.signal.onabort = () => {
console.log('abort');
(...other operations like closing connections to where your data comes from)
writer.close();
};
(...other logic)
return new NextResponse(stream.readable, {
headers: {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
'Cache-Control': 'no-cache, no-transform',
},
});
} |
Beta Was this translation helpful? Give feedback.
-
Edit: I don't think what I wrote below is totally right. Aborting doesn't close the writer it just aborts it , so it's open and aborted. Closing it just gives me that I think what's happening is the route handler is attempting to return the stream but it can't because it's been aborted. Then when you reload the client it creates a new stream, but the old one is still active. Not sure how to deal with it. Seems like the What I came up with is basically just to handle the errors. I think the writer.closed.catch((e) => {
console.log("--->writer.closed error", e);
});
writer.ready
.then(() => {
writer.write(encoder.encode(message));
})
.catch((e) => {
console.log("--->writer.ready error", e);
}); When the client aborts it throws I looked at these docs https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter |
Beta Was this translation helpful? Give feedback.
Sorry to hear it's not working for you. In my case I'm using this to read data from Kafka with KafkaJS and
req.signal.abort
solved it for me.If you're still getting "WritableStream is closed" errors, in my mind that could mean that the process that tries to write to the stream does not close properly in the
req.signal.abort
block, that used to be the issue for me during development.