Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Argument must be a string" with certain MongoDB ObjectID's in Node.js

I was getting an error like this in Node:

TypeError: Argument must be a string
    at TypeError (native)
    at Buffer.write (buffer.js:791:21)
    at serializeObjectId
    <snip>

the conditions were some uses of ObjectID's when doing a find operation with MongoDB. Some uses of ObjectID's raised this error and some did not. The only thing that mattered was where the ObjectID came from. If it was pulled from an existing collection, it worked. If I generated it myself (e.g., using ObjectID.createFromHexString), it failed as above.

like image 522
Chris Prince Avatar asked Jul 10 '16 04:07

Chris Prince


2 Answers

Change mongodb version to 2.1.6.

like image 109
Vainlyh Avatar answered Oct 04 '22 21:10

Vainlyh


I spent several hours tracking this one down. The problem came down to my use of Mongoose. I was using Mongoose schemas for some of my Collections and not using Mongoose for others. Here's the file containing my problematic code:

// Some common MongoDb operations and data.

'use strict';

var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var logger = require('./Logger');

var mongoose = require('mongoose');
// TODO: Take this out for production.
mongoose.set('debug, true');

var PSSharingInvitations = require('./PSSharingInvitations')

var connectedDb = null;

// Call this just once, at the start of the server.
// TODO: Need better error handling when can't initially connect. Right now have an ugly looking error when Mongo is not already started and we try to start our server.
exports.connect = function(mongoDbURL) {
    MongoClient.connect(mongoDbURL, function(err, db) {
        assert.equal(null, err);
        if (!db) {
            logger.error("**** ERROR ****: Cannot connect to MongoDb database!");
        }
        else {
            mongoose.connect(mongoDbURL);
            var db = mongoose.connection;
            db.on('error', console.error.bind(console, 'connection error:'));
            db.once('open', function() {
                // SCHEMA's
                exports.SharingInvitation = PSSharingInvitations.buildSchema(mongoose);

                logger.info("Mongoose: Connected to MongoDb database");
            });

            connectedDb = db;
            logger.info("Mongo: Connected to MongoDb database");
        }
    });
};

exports.db = function () {
    return connectedDb;
};

// Call this just once, when the server shuts down.
exports.disconnect = function() {
};

The problem turned out to be the line:

connectedDb = db;

Where db was the mongoose.connection. That is, I was using the mongoose.connection as my db for MongoDB Collections that were not using Mongoose. This caused intermittent errors.

The revised (and so far working!) code is as follows:

exports.connect = function(mongoDbURL) {
    MongoClient.connect(mongoDbURL, function(err, db) {
        assert.equal(null, err);
        if (!db) {
            logger.error("**** ERROR ****: Cannot connect to MongoDb database!");
        }
        else {
            connectedDb = db;
            logger.info("Mongo: Connected to MongoDb database");

            mongoose.connect(mongoDbURL);
            var connectedMongooseDb = mongoose.connection;
            connectedMongooseDb.on('error', console.error.bind(console, 'connection error:'));
            connectedMongooseDb.once('open', function() {

                // SCHEMA's
                exports.SharingInvitation = PSSharingInvitations.buildSchema(mongoose);

                logger.info("Mongoose: Connected to MongoDb database");
            });
        }
    });
};
like image 38
Chris Prince Avatar answered Oct 04 '22 23:10

Chris Prince