ttezel / twit

Twitter API Client for node (REST & Streaming API)
4.31k stars 569 forks source link

Twitter HTTP response body was not valid JSON #475

Open dovancao opened 6 years ago

dovancao commented 6 years ago

I got this problem when try to tweet with twitjs. Thank you for your help Code:

const config = require('../config');
var Twit = require('twit');

var client = new Twit({
  consumer_key: config.customerKey,
  consumer_secret: config.customerSecret,
  access_token: config.accessTokenApi,
  access_token_secret: config.accessTokenSecret,
  strictSSL: false,
});

tweetIt();

function tweetIt() {

  var r = Math.floor(Math.random()*100);

  tweet = {
    status: 'here is random number ' + r + '#coding_it'
  }

  client.post('statuses/update', tweet, tweeted);

  function tweeted(err, data, response) {
    if (err) {
      console.log('Something went wrong! ');
      console.log(err)
    } else {
      console.log('It worked')
    }
  }
}

Error:

 { Error: JSON decode error: Twitter HTTP response body was not valid JSON
larvata commented 6 years ago

I can't reproduce using the code you provided. Could post the details such as call stack?

Occult-Dev commented 5 years ago

I'm also having this issue, but for me it appears when trying to call the request_token endpoint. Here's my code:

const Twit = require('twit');
const config = require('./config');

const App = new Twit(config);

App.post("https://api.twitter.com/oauth/request_token").then(response => console.log(response));

The above code is literally the only thing I have in my script, and running node on it fails with the error:

Unhandled rejection Error: JSON decode error: Twitter HTTP response body was not valid JSON
    at Object.exports.makeTwitError (/home/spencer/Documents/TwitBot/node_modules/twit/lib/helpers.js:74:13)
    at onRequestComplete (/home/spencer/Documents/TwitBot/node_modules/twit/lib/twitter.js:333:27)
    at Request.<anonymous> (/home/spencer/Documents/TwitBot/node_modules/twit/lib/twitter.js:364:7)
    at Request.emit (events.js:187:15)
    at Gunzip.<anonymous> (/home/spencer/Documents/TwitBot/node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:273:13)
    at Gunzip.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1090:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
Occult-Dev commented 5 years ago

Any update on this, or anything more I can provide to help track this down?

c0rnonthec0bb commented 5 years ago

I'm getting the same issue with request_token

brentmarcus commented 5 years ago

Do you get the same error if you remove the # sign in #coding_it?

shalvah commented 5 years ago

Here's the offending line: https://github.com/ttezel/twit/blob/8eec3c672bba825c736ba93b74a445accd40f982/lib/twitter.js#L329

The JSON.parse fails, since the response body is not JSON, but this process resets the body to null, so even if you use the callback API, you get a null body.

The best workaround I could find was temporarily monkey-patching JSON.parse so it returns the original value if parsing fails:

        const originalJsonParse = JSON.parse.bind(JSON);
        JSON.parse = function (value) {
            try {
                return originalJsonParse(value);
            } catch (e) {
                return value;
            }
        }
        return t.post("https://api.twitter.com/oauth/request_token", {
            oauth_callback: callbackUrl,
       }).then(r => {
            JSON.parse = originalJsonParse;
            try {
                // Make sure it throws if there are any errors (errors are in JSON)
                const data = JSON.parse(r.data);
                if (data.errors) {
                    return Promise.reject(data);
                }
            } catch {
                return require('querystring').decode(r.data);
            }
        }).catch(e => {
            JSON.parse = originalJsonParse;
            throw e;
        });

(NB: you might also need to monkey-patch request.post, because the module doesn't add the callback URL to the oauth headers.

        const request = require("request");
        const originalRequestPost = request.post;
        request.post = (options) => {
            options.oauth.callback = callbackUrl;
            return originalRequestPost(options);
        }
        return t.post(url).then(r => {
            JSON.parse = originalJsonParse;
            request.post = originalRequestPost;
        }).catch(e => {
            JSON.parse = originalJsonParse;
            request.post = originalRequestPost;
        });
shalvah commented 4 years ago

If anyone's trying to implement Sign In With Twitter using Twit and running into this issue, I created a library for this that builds off Twit: https://github.com/shalvah/twittersignin

jafferkazmi572 commented 3 years ago

Facing same issue while getting media of Direct Messages. Following is the response

{ "success": false, "reason": { "message": "JSON decode error: Twitter HTTP response body was not valid JSON", "code": null, "allErrors": [], "twitterReply": null, "statusCode": 200 } }

https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/message-attachments/guides/retrieving-media

@ttezel