Skip to content

adapter.process() Causes Error: Cannot set headers after they are sent to the client #1005

@Noam-Microsoft

Description

@Noam-Microsoft

Version
1.3.1

Describe the bug
When using adapter.process(req, res, logic) and the end() closure is called with isInvokeResponseOrExpectReplies=true, it calls res.setHeader() after the bot logic completes:
Image

If the logic callback ends the response early (e.g., res.status(200).end() to flush a 200 before a long-running operation and avoid channel timeouts), the subsequent res.setHeader() call in end() throws:
Error: Cannot set headers after they are sent to the client
This was not an issue with the BotBuilder SDK, which did not call setHeader in the equivalent code path.

To Reproduce

  1. Call adapter.process(req, res, logic)
  2. Inside logic, call res.status(200).end() to send the response early
  3. The adapter's end() closure runs after logic completes and throws the error.

Expected behavior
adapter.process() should not throw if the response has already been sent by user code within the logic callback.

Suggested Fix
Add a res.headersSent guard in the end() closure:

const end = (status: StatusCodes, body?: unknown, isInvokeResponseOrExpectReplies: boolean = false) => {
    if (res.headersSent) {
        return
    }
    res.status(status)
    if (isInvokeResponseOrExpectReplies) {
        res.setHeader('content-type', 'application/json')
    }
    if (body) {
        res.send(body)
    }
    res.end()
}

Metadata

Metadata

Assignees

Labels

TriageNew issue, yet to be triaged

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions