Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first argument must be a string of Buffer #1904

Closed
novellizator opened this issue Nov 16, 2015 · 26 comments · Fixed by #1905
Closed

first argument must be a string of Buffer #1904

novellizator opened this issue Nov 16, 2015 · 26 comments · Fixed by #1905

Comments

@novellizator
Copy link

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...});
@simov
Copy link
Member

simov commented Nov 16, 2015

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

@novellizator
Copy link
Author

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

@simov
Copy link
Member

simov commented Nov 16, 2015

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

@novellizator
Copy link
Author

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

@simov
Copy link
Member

simov commented Nov 16, 2015

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?

@novellizator
Copy link
Author

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.

@simov
Copy link
Member

simov commented Nov 16, 2015

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.

@novellizator
Copy link
Author

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)});

@simov
Copy link
Member

simov commented Nov 16, 2015

Fixed here #1905

@novellizator
Copy link
Author

Super, thanks! :)

@umarovt
Copy link

umarovt commented Apr 9, 2016

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": "test@gmail.com",
        "mobilePhone": "+38631288288"
 };

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

I hope my code and question are clear enough.

@Ohar
Copy link

Ohar commented Apr 22, 2016

Got this error too.

@novellizator Can you reopen this please?

@simov
Copy link
Member

simov commented Apr 22, 2016

@banomaster @Ohar body must be String or Buffer

@Ohar
Copy link

Ohar commented Apr 22, 2016

@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
}

@simov
Copy link
Member

simov commented Apr 22, 2016

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.

@mboudreau
Copy link

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

@simov
Copy link
Member

simov commented Apr 29, 2016

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

@mboudreau
Copy link

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 notifications@github.com 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
#1904 (comment)

@simov
Copy link
Member

simov commented May 1, 2016

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.

@itsyogesh
Copy link

itsyogesh commented Jun 28, 2016

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.

@cozzbie
Copy link

cozzbie commented Sep 10, 2016

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

@smrutimandal
Copy link

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

@loretoparisi
Copy link

@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();
                        }
                    })
            })

@timgivois
Copy link

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)

@jeremyBanks
Copy link

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.

@arunsingh28
Copy link

i am also facing same error

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:558:11)
    at ServerResponse.header (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/response.js:771:10)
    at ServerResponse.contentType (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/response.js:599:15)
    at ServerResponse.send (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/response.js:145:14)
    at done (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/response.js:1008:10)
    at tryHandleCache (/Users/arun.singh28/Documents/Tracker/node_modules/ejs/lib/ejs.js:278:5)
    at View.exports.renderFile [as engine] (/Users/arun.singh28/Documents/Tracker/node_modules/ejs/lib/ejs.js:489:10)
    at View.render (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/view.js:135:8)
    at tryRender (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/application.js:640:10)
    at Function.render (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/application.js:592:3)
    at ServerResponse.render (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/response.js:1012:7)
    at /Users/arun.singh28/Documents/Tracker/node_modules/express-ejs-layouts/lib/express-layouts.js:113:20
    at tryHandleCache (/Users/arun.singh28/Documents/Tracker/node_modules/ejs/lib/ejs.js:278:5)
    at View.exports.renderFile [as engine] (/Users/arun.singh28/Documents/Tracker/node_modules/ejs/lib/ejs.js:489:10)
    at View.render (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/view.js:135:8)
    at tryRender (/Users/arun.singh28/Documents/Tracker/node_modules/express/lib/application.js:640:10)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.