Mongoose: doc.validate is not a function

Created on 28 Jan 2016  路  16Comments  路  Source: Automattic/mongoose

node_modules\mongoose\lib\schema\documentarray.js:104
      doc.validate({ __noPromise: true }, function(err) {
          ^

  TypeError: doc.validate is not a function

  - documentarray.js:104
    [hypetrain]/[mongoose]/lib/schema/documentarray.js:104:11

  - schematype.js:654 DocumentArray.SchemaType.doValidate
    [hypetrain]/[mongoose]/lib/schematype.js:654:22

  - documentarray.js:77 DocumentArray.doValidate
    [hypetrain]/[mongoose]/lib/schema/documentarray.js:77:35

  - document.js:1171
    [hypetrain]/[mongoose]/lib/document.js:1171:9

  - node.js:433 nextTickCallbackWith0Args
    node.js:433:9

  - node.js:362 process._tickCallback
    node.js:362:13

my schema;

var GameStatisticsSchema = new mongoose.Schema({
    game: { type: mongoose.Schema.ObjectId, ref: 'Game', required: true }, // associated game subverse.
    months: [
      { // monthly viewers
          epoch: { type: Number, required: true }, // entry time stamp
          weeks: [
            { // weekly viewers
                epoch: { type: Number, required: true }, // entry time stamp
                days: [
                  { // daily viewers
                      epoch: { type: Number, required: true }, // entry time stamp
                      hours: [
                        { // hourly viewers
                          epoch: { type: Number, required: true }, // entry time stamp
                          minutes: [
                            { // per minute statistics.
                                viewers: { type: Number },
                                channels: { type: Number },
                            }]
                      }]
                }]
          }]
    }]
});

Most helpful comment

Hi, I run into this issue for the first time today.

I can't tell exactly what is gonig on, if I find something I'll come back.

2016-05-04T10:14:56.990+00:00, [error], message: Uncaught error: doc.validate is not a function stack: TypeError: Uncaught error: doc.validate is not a function
    at /home/api/node_modules/mongoose/lib/schema/documentarray.js:120:13
    at DocumentArray.SchemaType.doValidate (/home/api/node_modules/mongoose/lib/schematype.js:682:12)
    at DocumentArray.doValidate (/home/api/node_modules/mongoose/lib/schema/documentarray.js:81:35)
    at /home/api/node_modules/mongoose/lib/document.js:1212:9
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)

so far I am not using doc.validate anywhere directly in my code.

and this is failing on a .save statement.

basically if i .save() a document, that has sub documents,and if one of those sub-documents is a plain object instead of a model, i get the error. does this make sense?

All 16 comments

@raistlinthewiz can you provide a code example that shows how you're creating the document you're trying to save?

@raistlinthewiz the below script executes without error for me on 4.4.2. Can you please see if the below script works for you, and, if so, provide a script that demonstrates the behavior you're seeing?

'use strict';

var assert = require('assert');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/gh3816');

var GameStatisticsSchema = new mongoose.Schema({
    months: [
      { // monthly viewers
          epoch: { type: Number, required: true }, // entry time stamp
          weeks: [
            { // weekly viewers
                epoch: { type: Number, required: true }, // entry time stamp
                days: [
                  { // daily viewers
                      epoch: { type: Number, required: true }, // entry time stamp
                      hours: [
                        { // hourly viewers
                          epoch: { type: Number, required: true }, // entry time stamp
                          minutes: [
                            { // per minute statistics.
                                viewers: { type: Number },
                                channels: { type: Number },
                            }]
                      }]
                }]
          }]
    }]
});

var Game = mongoose.model('Game', GameStatisticsSchema);

var obj = {
  months: [{
    epoch: 5,
    weeks: [{
      epoch: 5,
      days: [{
        epoch: 5,
        hours: [{
          epoch: 5,
          minutes: [{ viewers: 10, channels: 10 }]
        }]
      }]
    }]
  }]
};

Game.create(obj, function(error) {
  if (error) console.log(error.errors);
  assert.ifError(error);
  process.exit(0);
});

Issue's been stale for a while, closing. Re-open if this is still an issue.

I have the same issue.

C:\Users\syuilo\Desktop\projects\ssmatome\node_modules\mongoose\lib\schema\documentarray.js:120
        doc.validate({__noPromise: true}, callback);
            ^

TypeError: doc.validate is not a function
    at C:\Users\syuilo\Desktop\projects\ssmatome\node_modules\mongoose\lib\schema\documentarray.js:120:13
    at DocumentArray.SchemaType.doValidate (C:\Users\syuilo\Desktop\projects\ssmatome\node_modules\mongoose\lib\schematype.js:682:12)
    at DocumentArray.doValidate (C:\Users\syuilo\Desktop\projects\ssmatome\node_modules\mongoose\lib\schema\documentarray.js:81:35)
    at C:\Users\syuilo\Desktop\projects\ssmatome\node_modules\mongoose\lib\document.js:1191:9
    at nextTickCallbackWith0Args (node.js:453:9)
    at process._tickCallback (node.js:382:13)

My schema definition:

import {Schema, Connection, Document, Model} from 'mongoose';

/* tslint:disable:variable-name */

const base: Object = {
    registeredAt: { type: Date, required: true, default: Date.now },
    createdAt: { type: Date, required: false, default: null },
    title: { type: String, required: true },
    series: [{ type: Schema.Types.ObjectId, required: false, default: null, ref: 'Series' }],
    characters: [{ type: Schema.Types.ObjectId, required: false, default: null, ref: 'Character' }],
    tags: [{ type: Schema.Types.ObjectId, required: false, default: null, ref: 'SSTag' }],
    isDeleted: { type: Boolean, required: false, default: false }
};

export default function (db: Connection): Model<Document>[] {
    const baseSchema = new Schema(Object.assign({
        type: { type: String, required: true }
    }, base));

    const threadSchema = new Schema(Object.assign({
        url: { type: String, required: true, unique: true },
        type: { type: String, required: false, default: 'thread' },
        posts: [ new Schema({
            createdAt: { type: Date, required: true },
            number: { type: Number, required: true },
            text: { type: String, required: true },
            userName: { type: String, required: true },
            userId: { type: String, required: true },
            isMaster: { type: Boolean, required: false, default: true }
        })]
    }, base));

    if (!(<any>baseSchema).options.toObject) {
        (<any>baseSchema).options.toObject = {};
    }
    (<any>baseSchema).options.toObject.transform = (doc: any, ret: any) => {
        ret.id = doc.id;
        delete ret._id;
        delete ret.__v;
    };

    if (!(<any>threadSchema).options.toObject) {
        (<any>threadSchema).options.toObject = {};
    }
    (<any>threadSchema).options.toObject.transform = (doc: any, ret: any) => {
        ret.id = doc.id;
        delete ret._id;
        delete ret.__v;
    };

    const Base = db.model('SS', baseSchema, 'ss');
    const Thread = db.model('SSThread', threadSchema, 'ss');

    const init = Base.prototype.init;
    init.thread = (<any>new Thread()).__proto__;
    Base.prototype.init = function (doc: any, fn: any): any {
        const obj = init.apply(this, arguments);
        obj.__proto__ = init[doc.type];
        return obj;
    };

    return [
        Base,
        Thread
    ];
}
import * as mongoose from 'mongoose';
import config from '../config';

// Init mongo connection
const db = mongoose.createConnection(config.mongo.uri, config.mongo.options);

import ss from './schemas/ss';

export const SS = ss(db)[0];

My code:

SS.findById('hoge', (err, ss) => {
    ss.save();  // <- TypeError: doc.validate is not a function
});

Sorry my bad code and bad English. Thanks.

Can you do me a favor and convert that to es2015? I have never used typescript and don't want to set up a build system to repro a bug

I'm having the same issue. I'll see if I can debug the root cause tomorrow.

My issue was resolved by switching from a query/save to an upsert.

@vkarpov15
I ran into this issue as well. It happened when attempting to save an array of objects. I do not have a reproducible scripts for it though. Doing something like the following may cause the issue though.

Schema

{
    items: [
        {
            field1: {
                type: String
            },
            field2: {
                type: String
            }
        }
    ]
}

Psuedo Code

1. Query for a document.
2. Change one index of the array
3. Save document

I hope this helps resolve the problem.

What do you mean by "change one index of the array"?

I experienced this issue when trying to save a document with a schema such as:

var someSchema = mongoose.Schema({
property: [{ property: String}]
});

I assumed that this was invalid and changing it to:

var someSchema = mongoose.Schema({
property: []
});

fixed the issue.

@TomMettam the first bit should be perfectly valid. Can you provide a more complete code sample?

@vkarpov15
Sorry for the delayed response.
Example of changing array index:

var a = [
    {
        item0 : 0,
        item1 : 'Hello'
    },
    {
        item0: 1,
        item1: 'World'
    }];

a[0].item0 = 2;

@JperF still no dice, below script works fine for me:

'use strict';

var assert = require('assert');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/gh3816');

var mySchema = new mongoose.Schema({
    items: [
        {
            field1: {
                type: String
            },
            field2: {
                type: String
            }
        }
    ]
});

var Test = mongoose.model('test', mySchema);

var a = [
    {
        field0 : 0,
        field1 : 'Hello'
    },
    {
        field0: 1,
        field1: 'World'
    }];

Test.create({ items: a }, function(error, doc) {
  assert.ifError(error);
  Test.findById(doc._id).exec(function(error, doc) {
    assert.ifError(error);
    assert.ok(doc);
    doc.items[0].field0 = 1;
    doc.save(function(error) {
      assert.ifError(error);
      console.log('done');
      process.exit(0);
    });
  });
});

Hi, I run into this issue for the first time today.

I can't tell exactly what is gonig on, if I find something I'll come back.

2016-05-04T10:14:56.990+00:00, [error], message: Uncaught error: doc.validate is not a function stack: TypeError: Uncaught error: doc.validate is not a function
    at /home/api/node_modules/mongoose/lib/schema/documentarray.js:120:13
    at DocumentArray.SchemaType.doValidate (/home/api/node_modules/mongoose/lib/schematype.js:682:12)
    at DocumentArray.doValidate (/home/api/node_modules/mongoose/lib/schema/documentarray.js:81:35)
    at /home/api/node_modules/mongoose/lib/document.js:1212:9
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)

so far I am not using doc.validate anywhere directly in my code.

and this is failing on a .save statement.

basically if i .save() a document, that has sub documents,and if one of those sub-documents is a plain object instead of a model, i get the error. does this make sense?

@vkarpov15

I have create a script to reproduce the problem.

'use strict';

var assert = require('assert');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/gh3816');

var mySchema = new mongoose.Schema({
    items: [
        { month: Number, date: Date}
    ]
});

var Test = mongoose.model('test', mySchema);

var a = [
    {
        month : 0,
        date : new Date()
    },
    {
        month: 1,
        date : new Date()
    }];

Test.create({ items: a }, function(error, doc) {
    assert.ifError(error);
    Test.findById(doc._id).exec(function(error, doc) {
        assert.ifError(error);
        assert.ok(doc);
        doc.items[0] = {
            month: 5,
            date : new Date()
        };
        doc.save(function(error) {
            assert.ifError(error);
            console.log('done');
            process.exit(0);
        });
    });
});

This is reproducing the issue on my system.

doc.validate({__noPromise: true}, callback);
            ^

TypeError: doc.validate is not a function
    at ../node_modules/mongoose/lib/schema/documentarray.js:120:13
    at DocumentArray.SchemaType.doValidate (../node_modules/mongoose/lib/schematype.js:682:12)
    at DocumentArray.doValidate (../node_modules/mongoose/lib/schema/documentarray.js:81:35)
    at../node_modules/mongoose/lib/document.js:1212:9
    at nextTickCallbackWith0Args (node.js:420:9)
    at process._tickCallback (node.js:349:13)

馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ChrisZieba picture ChrisZieba  路  76Comments

floatingLomas picture floatingLomas  路  61Comments

bendytree picture bendytree  路  53Comments

joeytwiddle picture joeytwiddle  路  40Comments

ruimgoncalves picture ruimgoncalves  路  59Comments