Skip to content

ERR_HTTP_HEADERS_SENT when headers are sent while finalhandler waits for the request to finish #162

Description

@hata6502

When a request has an unread body, finalhandler waits for the request to finish before sending the response.

If another middleware or asynchronous operation sends the response headers during this wait, res.headersSent can be false when finalhandler is called and true when the onFinished callback runs.

The callback does not check res.headersSent again. It attempts to modify the already-sent headers with res.removeHeader(), causing the following exception:

ERR_HTTP_HEADERS_SENT
Cannot remove headers after they are sent to the client

If the exception is not caught, the Node.js process may exit.

Conditions

  1. The request body has not been fully read.
  2. finalhandler registers a response write with onFinished.
  3. Another operation sends the response headers before the request finishes.
  4. The request finishes and the registered write runs.

Expected behavior

If the response headers have already been sent when the onFinished callback runs, finalhandler should leave the response unchanged and should not throw an exception.

Related

#36 explains why finalhandler waits for the request body to be fully read before sending the response.

This issue concerns the response state changing during that wait, rather than the wait itself.

Activity

  1. krzysdz commented on Jul 26, 2026

    @krzysdz

    The waiting for request to end was introduced in 00633b4. Prior to this commit the function had been synchronous and the check had been performed immediately before setting headers and responding.
    Now the check is decoupled from action that depends on it and we have a TOCTOU. I wonder if this could be somehow turned into a DoS, but running into this would probably require a very interesting (and possibly buggy in other ways) code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions