hono icon indicating copy to clipboard operation
hono copied to clipboard

TypeError: Response body object should not be disturbed or locked

Open RobertSasak opened this issue 1 year ago • 25 comments

What version of Hono are you using?

3.9.0

What runtime/platform is your app running on?

Firebase functions

What steps can reproduce the bug?

Here is a simple example with POST end point.

import { getRequestListener } from '@hono/node-server'
import { Hono } from 'hono'

const app = new Hono()

app.post('/hello', async (c) => {
  return c.text('Hello World!')
})

export const web = onRequest(getRequestListener(app.fetch))

What is the expected behavior?

Requst should reach Heno and Hello World should appear.

What do you see instead?

There is an following silent error 500 when doing a POST request with payload. By placing an console.log in https://github.com/honojs/node-server/blob/3575d60a15e345700b81e22376825e98b0a69ebe/src/listener.ts#L42 it is possible to see this error.

TypeError: Response body object should not be disturbed or locked
    at extractBody (node:internal/deps/undici/undici:6433:17)
    at new Request (node:internal/deps/undici/undici:7314:48)
    at /<path>/functions/node_modules/@hono/node-server/dist/listener.js:48:33
    at /<path>/functions/lib/functions/src/index.js:79:64
    at /<path>/functions/node_modules/firebase-functions/lib/v2/providers/https.js:57:29
    at cors (/<path>/functions/node_modules/cors/lib/index.js:188:7)
    at /<path>/functions/node_modules/cors/lib/index.js:224:17
    at originCallback (/<path>/functions/node_modules/cors/lib/index.js:214:15)
    at /<path>/functions/node_modules/cors/lib/index.js:219:13
    at optionsCallback (/<path>/functions/node_modules/cors/lib/index.js:199:9)

Additional information

Similar issue is documented here https://github.com/honojs/node-server/issues/84

As far as I understand the issue occurs in https://github.com/honojs/node-server/blob/3575d60a15e345700b81e22376825e98b0a69ebe/src/listener.ts#L40 . Here the new Request is created from incoming request.

Firebase use expressjs to process all request and also expose Express JS Request object as an incoming. However this request is already "processed" and the actual body stream is already read.

So when on line https://github.com/honojs/node-server/blob/3575d60a15e345700b81e22376825e98b0a69ebe/src/listener.ts#L38 the read stream is create there is nothing to read.

I am not sure if this is an issue of Hono or how to approach it.

My workaround is to patch listner file and restore body from rawBody.

diff --git a/node_modules/@hono/node-server/dist/listener.js b/node_modules/@hono/node-server/dist/listener.js
index 3f5eaf7..e3541d0 100644
--- a/node_modules/@hono/node-server/dist/listener.js
+++ b/node_modules/@hono/node-server/dist/listener.js
@@ -38,7 +38,14 @@ const getRequestListener = (fetchCallback) => {
       headers: headerRecord
     };
     if (!(method === "GET" || method === "HEAD")) {
-      init.body = import_node_stream.Readable.toWeb(incoming);
+      // init.body = import_node_stream.Readable.toWeb(incoming);
+      init.body = new ReadableStream({
+        start(controller){
+          controller.enqueue(incoming.rawBody);
+          // controller.enqueue('{"c":"d"}');
+            controller.close();
+        }
+      });
       init.duplex = "half";
     }
     let res;

RobertSasak avatar Nov 14 '23 10:11 RobertSasak

Hi @RobertSasak,

Thank you for creating this. Since it's an issue with @hono/node-server (it's fine to create the issue here), could you first provide the version number of your @hono/node-server?

yusukebe avatar Nov 14 '23 11:11 yusukebe

Originaly I tested on 1.2.0. I have updated to 1.2.2 just now and the issue still occurs.

RobertSasak avatar Nov 14 '23 13:11 RobertSasak

I'm having this issue as well. Seems to have to do with that Readable.toWeb call.

Tested on Node 18.17.1, hono 3.10.2, @hono/node-server 1.2.3.

AverageHelper avatar Nov 23 '23 19:11 AverageHelper

The above workaround doesn't seem to work in my case. The Request gets constructed just fine, but when my handler calls c.req.json(), a TypeError: Received non-Uint8Array chunk is thrown.

AverageHelper avatar Nov 24 '23 05:11 AverageHelper

any head-way on this?

ZanzyTHEbar avatar Jan 12 '24 19:01 ZanzyTHEbar

c.req.json() and c.req.valid("json") don't work and make it almost unusable.

HananoshikaYomaru avatar Jan 18 '24 03:01 HananoshikaYomaru

Is there an update to this?

Looks like this might be related to: https://github.com/vercel/next.js/issues/50166 and https://github.com/FirebaseExtended/firebase-framework-tools/pull/122

noidwasavailable avatar Feb 08 '24 06:02 noidwasavailable

I had this identical issue with using vercel funcitons.

I found a solution that might help you further debug the problem.

A similar issue highlights the code in the vercel dev serve that causese the issue: https://github.com/honojs/node-server/issues/84#issuecomment-1844850121

The issue can be resolved by setting the following environment variable in your local environment file:

NODEJS_HELPERS="0"

It might be worth checking if Firebase Functions has similar behaviour

cogoo avatar Apr 02 '24 21:04 cogoo

Hi. Is this problem still happening? I don't have an environment for Firebase. If it's not resolved, I'll make it and try to investigate.

yusukebe avatar Apr 09 '24 08:04 yusukebe

This problem still happens when you cancel a request that is in progress

remorses avatar Jun 04 '24 16:06 remorses

has the exact same error using npm - 10.5.0, "vercel": "^35.2.3", "hono": "^4.5.1", "@hono/node-server": "^1.12.0", Switched over to bun, no such error anymore.

Bobetti avatar Aug 05 '24 12:08 Bobetti