Mongoose idGetter error: Cannot set property '_id' of null - node.js

I am getting the following error from the Mongoose idGetter function. Can anyone shed some light on what may be causing it?
return this.$__._id = null == this._id
^
TypeError: Cannot set property '_id' of null
at model.idGetter (e:\Users\Christine\test\mvt\node_modules\mongoose\lib\schema.js:98:23)
The error situation involves multiple client requests performing document removes (on different documents in the same collection), on a database being accessed over internet (i.e. slow response time). The failure happens on accessing the id of one of the removed documents. There appears to be a small timing window in which it occurs - everything I've tried to debug it causes the problem to 'go away'.
Outline of the application code:
Details.findOneAndRemove({ _id : remove_id}, afterRemove);
function afterRemove(err, removedDoc){
if (!err && removedDoc){
OtherDetails.find({ _id: some_id}, afterFind);
}
function afterFind(err, foundDoc){
if (!err && foundDoc){
// next line causes exception
if (foundDoc.details_id === removedDoc.id) { // do stuff };
}
}
}

Do you have an id property defined on the document that you have removed?
If not, you should probably want to compare foundDoc.details_id with removedDoc._id
Below is the source code for the idGetter function in the mongoose code base:
function idGetter () {
if (this.$__._id) {
return this.$__._id;
}
return this.$__._id = null == this._id
? null
: String(this._id);
}
As I understand, I think that the idGetter is specifically aimed at ObjectId types, hence that exception.
You could also try to add an id property on the document if it does not yet exist to see if it continues to throw the same exception.

fwiw: it is possible that the problem was related to using 32-bit Node on 64-bit Windows (8.1). After installing 64-bit Node, I could not reproduce the problem.
Unsatisfying level of certainty, but I thought I would share in case anyone else gets a similar problem or can shed light on whether this might really have been the cause.

Related

Firebase Cloud Function - Reference.update failed

I'm getting the following error when invoking a GCF:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
Done a bit of digging online but can't find the same issue. Without adding way too much info, I'm trying to add dish objects into a category object in Realtime Database. The odd thing is, the function works fine for the first 6 dishes, and when I try to add a 7th, this error pops up and the update method fails.
The full error log, with my unique property data is:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
'users.sIRf7m1uWfa9j0iF6UuuzvdD5TG2.dishcategories.default01.dishes.u3o1p278vriqo3odeslle.categories.0.dishes.irdrl2q7blsi1y7ih3jhh.categories.0.dishes.v8pl7r9llhfp7sqmz7uikk.categories.0.dishes.2ee3ajy6d5vymneewgflze.categories.0.dishes.btdib119nz5cnm6zk5uu4t.categories.0.dishes.4wyu5yqyn2z0bgvcejix9.categories.0.dishes.w1cfcpktym7nkp76p521n.categories.0.createdDate'
at ValidationPath.checkValid_ (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1035:19)
at ValidationPath.push (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1015:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1478:18
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
Here's the cloud function code from index.ts:
// Now we need to check if this dish's categories already exist as user categories.
// If they do, we can add this newly created dish into them.
// If they don't, we can create them with this newly added dish in them.
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish) // *** This is the update method producing the error in this case ***
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish)
}
})
Anyone know what this error means, and perhaps what I'm doing wrong here? Thanks!
The error message is quite explicit: you're trying to write data that is more than 32 levels deep, or which contains a cyclic object.
Given the code you shared, the latter seems most likely: you're looping over each category of a dish, and then write that dish to each category again. The simplest fix I can think of is to write the dish-without-categories to each category:
dish_without_categories = dish;
delete dish_without_categories.categories;
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
})

Azure Search - Error

When trying to index documents we are getting this error:
{"Token PropertyName in state ArrayStart would result in an invalid JSON object. Path 'value[0]'."}
Our code for indexing using the .NET library is :
using (var indexClient = new SearchIndexClient(searchServiceName, indexName, new SearchCredentials(apiKey)))
{
indexClient.Documents.Index(IndexBatch.Create(IndexAction.Create(documents.Select(doc => IndexAction.Create(doc)))));
}
Does anyone know why this error occurs?
The issue is because of an extra call to IndexAction.Create. If you change your indexing code to this, it will work:
indexClient.Documents.Index(IndexBatch.Create(documents.Select(doc => IndexAction.Create(doc))));
The compiler didn't catch this because IndexBatch.Create has a params argument that can take any number of IndexAction<T> for any type T. In this case, T was a collection, which is not supported (documents must be objects, not collections).
The programming model for creating batches and actions is changing substantially in the 1.0.0-preview release of the SDK. It will be more type-safe so that mistakes like this are more likely to be caught at compile-time.

Loopback - Model instance to JavaScript object

I have the following code:
MyUser.find().then(function (res) {
console.log(res[0]);
});
This effectively logs a model instance, which is fine. However, if I try to do this:
MyUser.find().then(function (res) {
delete res[0].name;
console.log(res[0]);
});
This delete statement doesn't work. Anyone knows why?
You did not provide any detail about the elements of the res array, but here is a possible cause.
Properties added to an Object using Object.defineProperty(obj, prop, descriptor) are, by default, immutable. Specifically, the descriptor property configurable, which defaults to false, determines whether the property is deletable.

Error in property accessor

We recently placed an MVC application in production that sometimes gives us unhandled errors that we cannot reproduce in our development environment. The web app keeps crashing on the same line but the inner exception gives different error messages. The line where it crashes is when a particular property is accessed (property accessor). But the inner exception gives us the following different errors:
Unable to cast object of type 'System.Int32' to type 'System.String'.
Index was outside the bounds of the array.
There is already an open DataReader associated with this Command which must be closed first.
We have a large number of users so I'm assuming that this has to do with concurrency or some type of thread problem? Can someone guide me in the right direction on how to find the problem?
By the way, it crashes always when accessing the same property. Sometimes it works other times it fails.
Here is the code for the accessor:
public string DepartementSelectionne
{
get
{
if (string.IsNullOrEmpty(m_departementSelectionne) == true)
if (ListeDepartements.FirstOrDefault() != null)
m_departementSelectionne = ListeDepartements.First().CodeDepartement;
return m_departementSelectionne;
}
set
{
m_departementSelectionne = value;
}
}
Thanks!

Cannot access properties on a populate()'d object from Mongoose?

This is very odd... I'm using populate() with a ref to fill in an array within my schema, but then the properties are inaccessible. In other words, the schema is like this:
new Model('User',{
'name': String,
'installations': [ {type: String, ref: 'Installations'} ],
'count': Number,
}
Of course, Insallations is another model.
Then I find & populate a set of users...
model.find({count: 0}).populate('installations').exec( function(e, d){
for(var k in d)
{
var user = d[k];
for(var i in user.installations)
{
console.log(user.installations[i]);
}
}
} );
So far so good! I see nice data printed out, like this:
{ runs: 49,
hardware: 'macbookpro10,1/x86_64',
mode: 'debug',
version: '0.1' }
However, if I try to actually ACCESS any of those properties, they're all undefined! For example, if I add another console log:
console.log(user.installations[i].mode);
Then I see "undefined" printed for this log.
If I try to operate on the object, like this:
Object.keys(user.installations[i]).forEach(function(key) { } );
Then I get a typical "[TypeError: Object.keys called on non-object]" error, indicating that user.installations[i] is not an object (even though it is outputted to the console as if it were). So, I even tried something ugly like...
var install = JSON.parse(JSON.stringify(user.installations[i]));
console.log(install, install.mode);
And, again, the first output (install) is a nice object containing the property 'mode'... but the 2nd output is undefined.
What gives?
Finally, I solved this...
I tried doing a console.log(typeof user.installations[i]); and got "string" as the output. This seemed odd, given that printing the object directly created console output (above) that looked like a normal object, not a string. So, I tried doing a JSON.parse(); on the object, but received the error "SyntaxError: Unexpected token r"
Finally, I realized what was going on. The "pretty console output" I described above was the result of a string formatted with \n (newlines). I had not expected that, for whatever reason. The JSON.parse() error is due to the fact that there is a known necessity with the node.js parser when attempting to parse object keys without quotations; see the SO question here:
Why does JSON.parse('{"key" : "value"}') do just fine but JSON.parse('{key : "value"}') doesn't? .
Specifically, note that the JSON parser in my case is failing on the character 'r', the fist character of "runs," which is the first key in my JSON string (above). At first I was afraid I needed to get a custom JSON parser, but then the problem hit me.
Look back to my original schema. I used a String-type to define the installation ref, because the array field was storing the installations's _id property as a String. I assume the .populate() field is converting the object to a String on output.
Finally, I looked at the Mongoose docs a little closer and realized I'm supposed to be referencing the objects based upon Schema.ObjectID. This explains everything, but certainly gives me some fixing to do in my schemas and code elsewhere...

Resources