Antoine Trouve
Antoine Trouve

Reputation: 1273

Express Response.send() throwing TypeError

I have this simple express code:

const api = Router()

api.post('/some-point', async (req, res, next) => {
  const someStuffToSend = await Promise.resolve("hello");
  res.json({ someStuffToSend });
})

It works well on my dev environment, but on the prod I get the error bellow:

TypeError: argument entity must be string, Buffer, or fs.Stats
    at etag (/[...]/node_modules/etag/index.js:83:11)
    at generateETag ([...]/node_modules/express/lib/utils.js:280:12)
    at ServerResponse.send ([...]/node_modules/express/lib/response.js:200:17)
    at ServerResponse.json ([...]/node_modules/express/lib/response.js:267:15)
    at api.post (/the/code/above)

I checked at node_modules/etag/index.js:83:11 and saw

if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
  throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
}

Before this code I added a printf to check the type of entity:

console.log("Entity contains", entity, "is of type", typeof entity, "with constructor", entity.constructor, "and is it a buffer?", Buffer.isBuffer(entity))

Which got me the output bellow:

Entity contains <Buffer 7b 22 70 72 65 64 69 63 74 69 6f 6e 5f 69 64 22 3a 22 63 4b 57 41 64 41 46 43 77 6e 55 43 22 2c 22 69 6e 69 74 69 61 6c 5f 70 72 65 64 69 63 74 69 6f ... > is of type object with constructor function Buffer(arg, encodingOrOffset, length) {
  if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
    return new Buffer(arg, encodingOrOffset, length)
  }

  // Common case.
  if (typeof arg === 'number') {
    if (typeof encodingOrOffset === 'string') {
      throw new Error(
        'If encoding is specified then the first argument must be a string'
      )
    }
    return allocUnsafe(this, arg)
  }
  return from(this, arg, encodingOrOffset, length)
} and is it a buffer? false

So it looks like the entity is a buffer, but not recognized as such. If I comment the test out, it crashed at a different location

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer
    at ServerResponse.end (_http_outgoing.js:747:13)
    at ServerResponse.send ([...]/node_modules/express/lib/response.js:221:10)
    at ServerResponse.json ([...]/node_modules/express/lib/response.js:267:15)
    at api.post (/the/code/above)

If you check at /node_modules/express/lib/response.js:221:10 you see

this.end(chunk, encoding);

where encoding is from a few lines above (l. 189, I checked with a printf)

chunk = Buffer.from(chunk, encoding)

I could hack the lib out to make that work, but I suspect some broken node_modules folder. However the error persists even after a rm package-lock.json; rm -rf node_modules; npm i.

Any clue on how to solve this would be very appreciated.

Below are my version numbers:

Edit 1

Edit 2

I removed the node_modules folder then npm i the packages one by one:

npm i aws-sdk body-parser bunyan check-types deepcopy duck-type express fast-csv glob handlebars http-auth md5 moment moment-timezone multer node-stream object-path randomstring

Still get the same error.

Edit 3

Add further information about the environment.

Edit 4

OK, figured out. It was a ts-node config related problem. I was launching my server with

ts-node --harmony_async_iteration -r tsconfig-paths/register ./src/index.ts

With the following lines in my tsconfig.json:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2017",
    "lib": [ "es2017", "esnext.asynciterable" ],
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "pretty": true,
    "paths": {
      "*": [
        "*", "src/*", "src/types/*",
        "node_modules/*"
      ]
    }
  },
  "include": [ "src/**/*" ]
}

Because of the -r tsconfig-paths/register in the command line, the paths specified in the tsconfig.json were loaded, including the "node_modules/*" in paths['*'].

I'm not sure why, but it looks like this was causing the libs in node_modules to be loaded twice, breaking the type checks based on constructors (such as instanceof).

Question

I'm not sure to completely understand the reason of that. Any light?

Upvotes: 2

Views: 2583

Answers (2)

Saravanan
Saravanan

Reputation: 911

I was getting this error,

TypeError: argument entity must be string, Buffer, or fs.Stats
    at etag (/[...]/node_modules/etag/index.js:83:11)
    at generateETag ([...]/node_modules/express/lib/utils.js:280:12)
    .....

I was trying to run a express project, and using webpack as bundler,

My error got resolved when I set target in webpack as 'node'

module.exports = (env) => {
    return {
      //....
      target: "node",
      //....,
      plugins: [
        // new NodePolyfillPlugin() // Don't add this plugin
       ]
    
    }
}

And make sure not to add NodePolyfillPlugin as pluging

Upvotes: 0

Anton Bessonov
Anton Bessonov

Reputation: 9813

I had very similar issue with typeorm and later with express too. The hint was in this conversation. My solution was to get rid * from paths.

Upvotes: 1

Related Questions