Request: first argument must be a string of Buffer

Created on 16 Nov 2015  ·  25Comments  ·  Source: request/request

Hi, I was running some code and got this error message:

_http_outgoing.js:441
    throw new TypeError('first argument must be a string or Buffer');
    ^

TypeError: first argument must be a string or Buffer
    at ClientRequest.OutgoingMessage.write (_http_outgoing.js:441:11)
    at Request.write (/Users/tomasnovella/workspace/kitt/kitt-chrome-sync/node_modules/request/request.js:1392:25)
    at end (/Users/tomasnovella/workspace/kitt/kitt-chrome-sync/node_modules/request/request.js:550:16)
    at Immediate._onImmediate (/Users/tomasnovella/workspace/kitt/kitt-chrome-sync/node_modules/request/request.js:578:7)
    at processImmediate [as _immediateCallback] (timers.js:383:17)

Funny thing is, that if I replace the current version of request module with an older one(### v2.60.0 (2015/07/21), according to changelog), everything works just fine.

The code that causes this error is this:

  request.post({
        url: '<someURL>',
        qs: {
          'client': 'Google+Chrome',
          'client_id': config.clientId
        },
        headers: {
          'Content-Type': 'application/octet-stream',
          'Authorization': 'Bearer '+ accessToken
        },
        encoding: null, //  if you expect binary data
        responseType: 'buffer', 
        body: body
    }, (error, response, body) => {..blah...});

Most helpful comment

Basically do not use body: {} in your request. If you want to pass data in the body, use json: {} instead

All 25 comments

What data type is body? Also there is no responseType property.

It's this: body = new Uint8Array(request.toArrayBuffer())
I know there's no resopnseType, but that shouldn't matter (since it worked), right?

So, basically the body should be either String or Buffer, not sure about these new types.

Well, in worked until now, so it means there was no problem _per se_ with sending this new built-in type(whatever that is and whatever the it's relationship to Buffer is),
only some if-condition was artificially added that throws an unneded error.

I found some hotfixes I could employ, I just find it somewhat unnecessary:
https://www.npmjs.com/package/uint8

The error is thrown from core, not from this module. That's most probably related to platform upgrade - in case you upgraded your NodeJS version. Are you using request in the browser? What if condition? What was working until now?

No, this error occurs, when I'm running it on node. It didn't happen until I upgraded npm (yesterday).
And then when I overwrote the node_modules/request with the old one, it started working again.
Then it's quite weird that the error is thrown from node core itself.

That's weird idd. I found two possible suspects in the past PRs, but I need your _exact_ code to reproduce the bug - a small self contained code example that I can run.

How about this code?

var request = require('request');
request.post({
        url: 'https://clients4.google.com/chrome-sync/command',
        qs: {
          'client': 'Google+Chrome',
           'client_id': '12345'
        },
        headers: {
          'Content-Type': 'application/octet-stream',
          'Authorization': 'Bearer 123'
        },
        encoding: null, //  if you expect binary data
        responseType: 'buffer',
        body: new Uint8Array(3)
      }, function(e,r,b){console.log(e,r,b)});

Fixed here #1905

Super, thanks! :)

Hey guys,

i have version 2.70.0 installed, but I am still struggling with this same error:

TypeError: first argument must be a string or Buffer
    at ServerResponse.OutgoingMessage.end (_http_outgoing.js:524:11)
    at /Users/urbanmarovt/Documents/Faks/BCH/Diploma/PoC/gateway/routes/index.js:87:17
    at Request._callback (/Users/urbanmarovt/Documents/Faks/BCH/Diploma/PoC/gateway/routes/proxy.js:81:7)
    at Request.self.callback (/Users/urbanmarovt/Documents/Faks/BCH/Diploma/PoC/gateway/node_modules/request/request.js:200:22)

This is my code that I currently use:

var options = {
      url: url,
      path: req.path,
      qs: req.query,
      method: req.method,
      headers: headers,
      responseType: 'buffer',
      timeout: TIMEOUT
    };

 options.json = true;
 options.body = {
        "firstName": "Test1",
        "lastName": "Test2",
        "email": "[email protected]",
        "mobilePhone": "+38631288288"
 };

 request(options, function (error, response, body) {
      callback(error, response, body, options);
    });

I hope my code and question are clear enough.

Got this error too.

@novellizator Can you reopen this please?

@banomaster @Ohar body must be String or Buffer

@simov Oh thank you.
I used

res.write(data);
res.end();

it returns JSON, but I get this issue (#1904) on remote server.
Using res.json() fix problem, bcz it escapes JSON and stringify it. But I need get JSON in response and when I use res.json, it send me an escaped string instead.
Can you please help me with that?

Example

Handler

function foo (req, res) {
  request.post(
    'https://example.com/api',
    {form: data},
    function (error, response, body) {
      res.json(body);
    }
  );
}

Actual resonse

"{\"response\":{\"data\":{}},\"status\":0}"

Desired response

{
    "response": {
        "data": {}
    },
    "status": 0
}

Set the json option to true, also take a look at the options section in the docs.
Your last question is not related to this issue, post a new one if you have other questions.

Wow, bravo request team, way to break the interface without upgrading major versions :/

@mboudreau can you open up another issue and explain exactly what isn't working for you?

Essentially, I have been using request since 2.64.x, and I've always just
used an object in the body which was serialized automatically by request,
but since the latest version, this isn't the case anymore. This essentially
broke several of my builds at the same time when the new version came out
with a very cryptic error message.

The reason I'm annoyed is because of the semantic versioning standard says
that when a breaking change is being introduced, the major version needs to
be incremented. As you can see from this thread, the latest feature version
broke for many and personally causing me a lot of frustration and wasted
time trying to figure or this error.

I don't think it deserves it's own ticket, but just a warning of the
changes and to make sure to follow semantic versioning correctly.

On Fri, Apr 29, 2016, 5:28 PM simo [email protected] wrote:

@mboudreau https://github.com/mboudreau can you open up another issue
and explain exactly what isn't working for you?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
https://github.com/request/request/issues/1904#issuecomment-215646824

I'm still not sure what is the expected behavior in your case? Are you expecting to pass an object to the body option and send a stringified JSON or a querystring body?

Either way, you should provide a code example to reproduce the bug. From the docs:

body - entity body for PATCH, POST and PUT requests. Must be a Buffer, String or ReadStream. If json is true, then body must be a JSON-serializable object.

You can test this:

request({
  method: 'POST',
  url: 'http://requestb.in/tr4jaxtr',
  body: {a: 1},
  json: true,
  callback: (err, res, body) => {
    if (err) {
      console.log(err)
    }
    console.log(body)
  }
})

See the results here. As you can see the body is a stringified JSON object.

Hey everyone, I have been fiddling with this error for a while, and here is what I found out. When the post request params is of type: {form: {key: 1}} it automatically serializes the post parameters, but when it is something else, say {body: {key: 1}} it throws the new TypeError('first argument must be a string or Buffer'); error.

To overcome this, I just did {body: JSON.stringify({key: 1})} and the request succeeded. I haven't looked into the source yet, but this worked for me.

Also, if we set json: true in the options object, it automatically serializes the request params.

Basically do not use body: {} in your request. If you want to pass data in the body, use json: {} instead

Sometimes the best answers are the very bottom of a thread. Thanks @itsyogesh @cozzbie

@novellizator guys this was a closed issue, but I'm puzzled since I'm doing that for a binary image and get the same error:

app.post(self._options.baseUrl + '/image.post', function (req, res) {

                delete req.headers.host;

                var headers= req.headers;
                headers['Content-Type'] = 'application/octet-stream';

                request.post('http://localhost:9080/image.post',
                    {
                        headers: headers,
                        encoding: null, //  if you expect binary data
                        responseType: 'buffer',
                        body: req.body
                    },
                    function (error, response, body) {
                        if (!error && response.statusCode == 200) {
                            res.send(body);
                            res.end();
                        } else {
                            res.send({ error: new Error('image error') });
                            res.end();
                        }
                    })
            })

Hey, just came across with a solution to this. I was sending a json body, but I needed to convert it to string with body: JSON.stringify(body)

I was using a Uint8Array as my body without error, but when I sent a request where the array had zero-length, it was suddenly throwing an error. Probably a bit of a validation bug there, one way or the other.

Was this page helpful?
0 / 5 - 0 ratings