processing / processing/p5.js-web-editor

Double Response (ERR_HTTP_HEADERS_SENT) in addProjectToCollection controller

Open
#3,964 5 comments 0 reactions 1 assignee View on GitHub

@dpoppe7 is already working on this.

Since Mar 10, 2026.

Bug
Dominant language
JavaScript
Stars
1.7k
Forks
1.7k
Avg merge
3d 4h
Merged PRs (30d)
8

Description

p5.js version

1.11.11

What is your operating system?

Mac OS

Web browser and version

Safari 17.6

Actual Behavior

The addProjectToCollection controller (found in server/controllers/collection.controller.js) contains a logic flaw in its Promise handling that leads to a server crash (ERR_HTTP_HEADERS_SENT).

When a validation error occurs (e.g. a collection or a project is not found), the updateCollection function correctly sends a failure response to the client. However, it then returns null to the next block in the Promise chain rather than "short-circuiting" the execution.

addProjectToCollection.js :

First response sent to client here.
Returning 'null' doesn't stop the Promise chain. It passes 'null' to the next .then() block.

function updateCollection([collection, project]) {
    if (collection == null) {
      sendFailure(404, 'Collection not found');
      return null;
    }

Then, even if updateCollection returned null, .then(populateReferences) runs.
Second response occurs when .then(sendSuccess), attempts to send 200OK and crash.

return Promise.all([collectionPromise, projectPromise])
  .then(updateCollection) 
  .then(populateReferences)
  .then(sendSuccess)         
  .catch(sendFailure);

Error in Terminal:

node:_http_outgoing:655
throw new ERR_HTTP_HEADERS_SENT('set');
^

Error: Cannot set headers after they are sent to the client

Expected Behavior

When a resource (Collection or Project) is not found, the server should respond with a 404 Not Found and terminate the request lifecycle immediately.

The Promise chain should be short-circuited so that subsequent .then() blocks (like populateReferences and sendSuccess) are never executed after a failure response has been sent. The Node process should remain operational, and no ERR_HTTP_HEADERS_SENT error should be triggered.

Steps to reproduce
Steps:

This bug is triggered by a race condition where the Frontend UI becomes "stale" due to actions in another session/tab. For example:

  1. Ensure user is logged in
  2. Open the p5.js Web Editor in two separate browser tabs (Tab A and Tab B).
  3. In Tab A: Open the "Add to Collection" modal for any sketch. The list of existing collections is displayed, if none, create one.
  4. In Tab B, delete the collection that you intend to add the sketch to.
  5. Back in Tab, click the button to add the sketch to that (now deleted) collection.

Observed Result: The server identifies the collection is missing, sends a 404, but then fails to stop execution, attempts a second response, and crashes the backend process.

Also happens when: user has a sketch open in Tab A, deletes it in Tab B, and then attempts to add the now deleted sketch from Tab A to a collection.

https://github.com/user-attachments/assets/f27acf43-2d59-4b4c-b5a5-2eb618369755

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.