cloudant / nodejs-cloudant

Cloudant Node.js client library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Uploading empty attachment file produces TypeError: Cannot read property 'resume' of undefined

tomanwalker opened this issue · comments

commented

Please read these guidelines before opening an issue.

Bug Description

1. Steps to reproduce and the simplest code sample possible to demonstrate the issue

var Cloudant = require('@cloudant/cloudant');
var config = require('../config.js');

var con = new Cloudant({
		url: config.cloudant_host,
		plugins:{
			iamauth:{
				iamApiKey: config.cloudant_key
			}
		}
	});
var myDB = con.use(config.MY_DB_NAME);

myDB.attachment.insert(docId, pictureId, pictureObj, contentType, { rev: doc._rev}, function(err, saved_doc) {
	log.debug('uploadPicture done');
	if (!err)
		return resolve(saved_doc);
	else{
		log.debug('returning err');
		error.message = err.message;
		error.statusCode = "CLOUDANT_ERROR";
		error.httpHeader = 503;
	        return error;
	}
});

2. What you expected to happen

IAM-plugin to work

3. What actually happened

Random crashes, especially working with attachments.

January 8th 2019, 07:58:36.050 npm ERR! errno 1
January 8th 2019, 07:58:36.049 at updateState (/home/vcap/app/node_modules/@cloudant/cloudant/lib/clientutils.js:53:3)
January 8th 2019, 07:58:36.049 at IAMPlugin.onError (/home/vcap/app/node_modules/@cloudant/cloudant/plugins/base.js:50:5)
January 8th 2019, 07:58:36.049 at replenish (/home/vcap/app/node_modules/@cloudant/cloudant/node_modules/async/dist/async.js:1025:25)
January 8th 2019, 07:58:36.049 at iterateeCallback (/home/vcap/app/node_modules/@cloudant/cloudant/node_modules/async/dist/async.js:1015:17)
January 8th 2019, 07:58:36.049 at /home/vcap/app/node_modules/@cloudant/cloudant/lib/clientutils.js:137:11
January 8th 2019, 07:58:36.049 at /home/vcap/app/node_modules/@cloudant/cloudant/node_modules/async/dist/async.js:988:16
January 8th 2019, 07:58:36.048 at /home/vcap/app/node_modules/@cloudant/cloudant/node_modules/async/dist/async.js:484:16
January 8th 2019, 07:58:36.048 at /home/vcap/app/node_modules/@cloudant/cloudant/lib/clientutils.js:154:11
January 8th 2019, 07:58:36.048 at processState (/home/vcap/app/node_modules/@cloudant/cloudant/lib/clientutils.js:118:14)
January 8th 2019, 07:58:36.048 TypeError: Cannot read property 'resume' of undefined
January 8th 2019, 07:58:36.047 r.response.resume();

Environment details

I had no problem uploading an attachment in this way using IAM credentials.

Please complete the bug template's Environment details so we can better debug the issue.

You said you expected the "IAM-plugin to work". Does that mean you only see these issues when using the iamauth plugin, but specifically not when using other credentials?

commented

@ricellis
Thanks for the reply)

Yeah, I couldn't collect more than Error stackTrace. The issue seem to appear randomly (once in a few days) - thus I might think it have smth to do with token refresh, but no sure.

you said you expected the "IAM-plugin to work

well, I can see in the stackTrace the exception is originated there, thus the claim

Ideally, can the library be patched to provide more insights about why "r.response" variable is undefined in @cloudant/cloudant/lib/clientutils.js:118:14 - I'd be happy then to provide output when the issue fires again.

If you can reproduce with the debug env vars:

DEBUG=cloudant*,nano
NODE_DEBUG=request

then there will probably be enough additional context to better detect the issue, but it will be very verbose and you'll probably want to check and redact anything sensitive before uploading anything as it will include HTTP headers etc.

I think tokens are valid for 60 minutes by default, so I'd be surprised if a refresh issue only showed up every few days.

commented

Hi, I've got a way to reproduce the issue. Turns out it happens with an empty file.
@ricellis

Program

// ## config
var apikey = "***";
var host = "https://55faa453-1121-4832-a165-b499339d0e8e-bluemix.cloudant.com";
var dbname = "random-db";

var targetDoc = {
	"_id": "0056318860f19ad9e5853179fb9602e4",
	"_rev": "2-d7b79405b99b933fb76cc5d4ac4f9bc1"
};

// ## dependencies
var Cloudant = require('@cloudant/cloudant');
var fs = require('fs');

// ## flow
console.log('Before cloudant connection...');
var connection = new Cloudant({
	url: host,
	plugins:{
		iamauth:{
			iamApiKey: apikey
		}
	}
});

mydb = connection.use(dbname);

console.log('Before File read...');
var myFile = fs.readFileSync('testData/empty_file.txt'); // File is an empty text file

console.log('Before File insert...');
mydb.attachment.insert(targetDoc._id, 'testFile.txt', myFile, 'plain/txt', { rev: targetDoc._rev}, function(err, body) {

	if(err){
		console.log('err = %s', JSON.stringify(err));
	}
	else{
		console.log('ok = %s', JSON.stringify(body));
	}
});

Output

$ node ./couch_issue.js
Before cloudant connection...
Before File read...
Before File insert...
C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\lib\clientutils.js:118
  r.response.resume();
             ^

TypeError: Cannot read property 'resume' of undefined
    at processState (C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\lib\clientutils.js:118:14)
    at C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\lib\clientutils.js:154:11
    at C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\node_modules\async\dist\async.js:484:16
    at replenish (C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\node_modules\async\dist\async.js:1025:25)
    at iterateeCallback (C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\node_modules\async\dist\async.js:1015:17)
    at C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\node_modules\async\dist\async.js:988:16
    at updateState (C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\lib\clientutils.js:53:3)
    at C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\lib\clientutils.js:137:11
    at IAMPlugin.onError (C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\plugins\base.js:50:5)
    at C:\DFL\Workbench\app\node_modules\@cloudant\cloudant\lib\clientutils.js:136:25

Thanks, we'll look into it.

We need to do a fix here to correctly propagate the underlying error instead of failing with the TypeError.

The underlying error is Error: Argument error, options.body. caused by request/request#920
There appears to be a PR open for that issue in request so hopefully we can consume a fixed version in the not too distant future.

Thanks @smithsz for digging that up

Closing as it seems that the upstream PR is unlikely to ever get merged given that request is deprecated.

In our new cloudant-node-sdk(beta) a zero length attachment uploads without error. There is an example of using putAttachment in the docs.