I'm building an app with node/express/mongo/mongoose. I've encountered an error that I can't seem to figure out and googling around has so far not been helpful.
I've created a simplistic, cat-themed example to recreate the error I'm encountering. I'm basically trying to retrieve an object by its ObjectId. I'm using the object id (as a string) that was automatically generated when I created the object.
When I navigate to the path localhost:3000/kitty/586d62878fc14d30e0ac5379 I get the following error: 'Cast to ObjectId failed for value "586d62878fc14d30e0ac5379" at path "_id" for model "Kitten"'. The offending line of code is my call to model.Kitten.findById() [see below].
As far as I can tell, the ObjectId string is valid.
I've tried casting my string object id to a mongoose object id and passing this in to findById instead of the string value, but this only produces a strange "hex is not a function" error, and besides, I am under the impression that this is unnecessary because mongoose automatically casts a valid string id to an object id.
I'm using a hosted mongodb instance (mlab).
Here is my code for reference:
Package.json:
{
"name": "testapp",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.15.2",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
"express": "~4.14.0",
"jade": "~1.11.0",
"mongodb": "^2.2.19",
"mongoose": "^4.7.6",
"morgan": "~1.7.0",
"serve-favicon": "~2.3.0"
}
}
app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
index.js:
var express = require('express');
var router = express.Router();
var model = require('./model');
var mongoose = require('mongoose');
/* GET home page. */
router.get('/kitty/create', function(req, res, next) {
var fluffy = new model.Kitten({ name: 'fluffy' });
fluffy.save(function(err, fluffy){
if(err) return next(err);
res.render('index', { title: 'Express' });
});
});
router.get('/kitty/:id', function(req, res, next){
// find kitty by id
model.Kitten.findById(req.params.id, function(err, kitty){
if(err) return next(err);
if(!kitty){
res.send('no kitty found');
} else {
res.send(kitty._id);
}
});
});
module.exports = router;
model.js:
var mongoose = require('mongoose');
mongoose.connect('mongodb://xxxxx:xxxxx#xxxxx.mlab.com:xxxxx/xxxxx');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
var kittySchema = mongoose.Schema({
name: String
});
var Kitten = mongoose.model('Kitten', kittySchema);
exports.Kitten = Kitten;
});
Any insight you can offer would be greatly appreciated.
I was having the exact same problem. There seems to be an issue with mongoose version. I downgraded from 4.7.6 to 4.7.2 (the last version I was using before upgrading) and no more problem.
I don't know exactly in which version the problem was introduced, but based on the absence of answers when googling, maybe it's 4.7.6 (released on 2017-01-02).
Just doing
npm install --save mongoose#4.7.2
will fix it for now.
Hope this helps :)
Edit:
It's definitely a bug on versions after 4.7.2
https://github.com/Automattic/mongoose/issues/4867#issuecomment-270342054
Related
All my projects were working fine before but all of sudden the content of the body is not being saved as if the body is not being parsed or something. Just to check I created this simple project of book directory but no luck.
Any help would be appreciated.
Thank you
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mongoose = require('mongoose');
var config = require('./config');
// import bodyParser from "body-parser";//for typscript code only, use require for js
// app.use(bodyParser.json());
// app.use(bodyParser.urlencoded({ extended: false }));
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var bookRouter = require('./routes/books_routes');
const url = config.mongoURL;
const connect = mongoose.connect(url);
connect.then((DB)=>{
console.log("Connected With the MongoDB Server");
},(err)=>{next(err)})
.catch((err)=>next(err));
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({
extended: true
})); //Parse URL-encoded bodies
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/books',bookRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Route File
const express = require('express');
const mongoose =require('mongoose');
const Books = require('../models/books');
const bookrouter = express.Router();
// bookrouter.use(bodyparser.json());
bookrouter.use(express.json());
bookrouter.use(express.urlencoded({
extended: true
})); //Parse URL-encoded bodies
bookrouter.route('/')
.get((req,res,next)=>{
Books.find({})
.then((books)=>{
res.statusCode = 200;
res.setHeader('content-Type','application/json');
res.json(books);
},(err)=>{next(err)})
.catch((err)=>next(err))
})
.post((req,res,next)=>{
var book = new Books({
book_name: req.body.book_name,
book_author: req.body.book_author,
book_description: req.body.book_description
})
book.save()
.then((book)=>{
Books.findById(book._id)
.then((book)=>{
res.statusCode = 200;
res.setHeader('content-type','application/json');
res.json(book);
},(err)=>next(err))
})
})
.put((req,res,next)=>{
res.send("PUT request is not supported at this API");
})
.delete((req,res,next)=>{
Books.remove({})
.then((resp)=>{
res.statusCode=200;
res.setHeader('content-type','application/json');
res.send(resp);
})
})
module.exports = bookrouter;
Model file
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportlocalmongoose = require('passport-local-mongoose');
var Books = new Schema({
book_name :{
type:String
},
book_author:{
type:String
},
book_description:{
type:String
}
},{
timestamps:true
})
Books.plugin(passportlocalmongoose);
module.exports = mongoose.model('Book',Books);
package.json
{
"name": "books-directory",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "^1.19.0",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"jade": "~1.11.0",
"mongodb": "^3.0.10",
"mongoose": "^5.1.7",
"mongoose-currency": "^0.2.0",
"morgan": "~1.9.1",
"passport": "^0.4.0",
"passport-local": "^1.0.0",
"passport-local-mongoose": "^5.0.1"
}
}
Given is:
/routes/index.js
var express = require('express');
var router = express.Router();
//var mongo = require('mongodb').MongoClient;
//var objectId = require('mongodb').ObjectID;
var mongo = require('mongodb');
var assert = require('assert');
var url = 'mongodb://localhost:27017/test';
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
router.post('/insert', function(req, res, next) {
var item = {
title: req.body.title,
content: req.body.content,
author: req.body.author
};
mongo.connect(url, function(err, db) {
assert.equal(null, err);
db.collection('userdata').insertOne(item, function(err, result) {
assert.equal(null, err);
console.log('Item inserted');
db.close();
});
});
res.redirect('/');
});
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var hbs = require('express-handlebars');
var expressValidator = require('express-validator');
var expressSession = require('express-session');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.engine('hbs', hbs({extname: 'hbs', defaultLayout: 'layout', layoutsDir: __dirname + '/views/layouts/'}));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public'))); eingetragen)
app.use(expressValidator());
app.use(express.static(path.join(__dirname, 'public')));
app.use(expressSession({secret: "eefa56_50cacb_34634f", saveUninitialized: false, resave: false})); // dafault storage is RAM, otherwise kann ich in der API von express-session rumwühlen, da der storage serverseitig in einer DB erfolgt
app.use('/', indexRouter);
app.use('/users', usersRouter);
...
package.json
{
"name": "sample_express_app(POST_GET_handlebars)",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"assert": "^1.4.1",
"body-parser": "^1.18.3",
"cookie-parser": "~1.4.3",
"debug": "~2.6.9",
"express": "~4.16.0",
"express-handlenter": "^3.0.0",
"express-session": "^1.15.6",
"express-validator": "^5.3.0",
"http-errors": "~1.6.2",
"mongodb": "^3.1.4",
"morgan": "~1.9.0"
}
}
The mongoDB server is running and there is no issue to manipulate the database in the CMD. It especially deals with the router.post('/insert' ... in /routes/index.js. There is something wrong(but maybe at another point too).
I also tried it with this (either I get the error db.collection('userdata').insert(... --> 'db.collection is not a function' or db.userdata.insert(... --> 'cannot read property insert'):
1)
db.runCommand({
insert: "userdata",
documents: [ item ]
}
)
2)
db.collection('userdata').insertOne(item, function(err, result) {
assert.equal(null, err);
console.log('Item inserted');
db.close();
});
3)
db.userdata.insert(item, function(err, result) {
assert.equal(null, err);
console.log('Item inserted');
db.close();
});
Native mongoDB driver works with the help of MongoClient.
Make changes in the index.js file
var mongo = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
mongo.connect(url, function(err, client) {
const db = client.db(dbName);
//your db queries
})
refer mongodb
Have a problem with using another method in class.
I'm working with express framework and have to use Ecma Script 6.
When I try to use method in the same class I have an error:
Cannot read property 'generatePassword' of undefined
TypeError: Cannot read property 'generatePassword' of undefined
at createUser (E:\OpenServer\domains\testNode\app\controllers\users.js:5:13)
at Layer.handle [as handle_request] (E:\OpenServer\domains\testNode\node_modules\express\lib\router\layer.js:95:5)
at next (E:\OpenServer\domains\testNode\node_modules\express\lib\router\route.js:131:13)
at Route.dispatch (E:\OpenServer\domains\testNode\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (E:\OpenServer\domains\testNode\node_modules\express\lib\router\layer.js:95:5)
at E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:277:22
at Function.process_params (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:330:12)
at next (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:271:10)
at Function.handle (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:176:3)
at router (E:\OpenServer\domains\testNode\node_modules\express\lib\router\index.js:46:12)
My code:
Route: /routes/users.js
const express = require('express');
const router = express.Router();
const users = require('../app/controllers/users');
router.get('/', users.createUser);
module.exports = router;
Controller: /app/controllers/users.js
class Users
{
createUser(req, res)
{
this.generatePassword();
res.json({msg: "The method return user data" });
}
generatePassword()
{
return 'The method return new password';
}
}
module.exports = new Users();
Main App file: /app.js
const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const index = require('./routes/index');
const users = require('./routes/users');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
package.json
{
"name": "testnode",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.15.2",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
"express": "~4.14.0",
"hbs": "~4.0.1",
"morgan": "~1.7.0",
"serve-favicon": "~2.3.0"
}
}
Help me please, thank you.
In the line that causes the error, the object this is not what you think it is. To solve this, replace the following:
router.get('/', users.createUser);
with:
router.get('/', users.createUser.bind(users));
This will make sure when eventually that function is called by the router.get implementation, it will be called with the this object set to users.
I'm having issues deploying my app on Heroku. I keep getting a screen in my browser saying Application Error. From what i've read this is something with MongoLab.
I have set my PROCESS.ENV.MONGOLAB_URI correctly on heroku and I can't get it to work. I have also tried adding a new user to MongoLAB for this DB and even that user won't work as well.
I am Process.env.PORT because I am using Socket.io. Is it something in my app.js?
var express = require('express');
var http = require('http')
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.connect(process.env.MONGOLAB_URI || 'mongodb://localhost/queueThat');
var db = mongoose.connection;
var routes = require('./routes/index');
var app = express();
var server = http.createServer(app);
//Stuff for Sockets
var io = require('socket.io').listen(server);
//sockets
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require('ejs').renderFile);
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
//Connect to the Socket
io.on('connection', function(socket){
socket.on('song send', function(song){
io.emit('song send', song)
console.log('artist on')
})
socket.on('artist send', function(artist){
console.log('artist on')
io.emit('artist send', artist)
})
//Disconnect
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var port = (process.env.PORT || 8000);
server.listen(port, function() {
console.log("Listening on " + port);
});
module.exports = app;
I have also tried adding my node and NPM versions to no avail. Any ideas? Package.json looks like this.
{
"name": "queueThat",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"ejs": "^2.3.4",
"express": "~4.13.1",
"mongoose": "*",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"socket.io": "*"
},
"engines": {
"node": "5.4.0",
"npm": "3.3.12"
}
}
Application Error doesn't mean that there is something wrong with MongoLAB, not necessarily.
To be clear you need to double check few places:
You need to have proper Procfile in the root folder of your project
Be aware of postinstall npm script.
Also you could check your logs on heroku heroku logs -n 200 (200 or more lines if needed) to be sure what's the problem you have.
I am newbie to Nodejs. I have an app.js and an index.js inside the route directory. I have an app.use(multer....). I also have app.post('filter-reports') defined which actually uploads the file contents to the server.
I have business logic to be performed and have configured the routes inside the routes/index.js file where I intend to configure the /filter-reports route. Please help me understand where I am going wrong. I need to upload the file using the multer also run my business logic present in the index.js file.
app.js source code:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var _ = require('underscore');
var cache = require('js-cache');
var multer = require('multer');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
var done=false;
app.use(multer({ dest: './uploads/',
rename: function (fieldname, filename) {
return filename+Date.now();
},
onFileUploadStart: function (file) {
console.log(file.originalname + ' is starting ...')
},
onFileUploadComplete: function (file) {
console.log(file.fieldname + ' uploaded to ' + file.path)
done=true;
}
}));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.post('filter-reports',function(req,res){
console.log('Working on the filtered reports....');
if(done==true){
console.log(req.files);
res.end("File uploaded.");
}
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
var express = require('express');
var request = require("request");
var _ = require('underscore');
var jscache = require('js-cache');
var schedule = require('node-schedule');
var filename;
In the index.js file
var router = express.Router();
router.post('/filter-reports', function(req, res) {
console.log('Came inside the Node js router.. Now.. its all up to me to format the data....');
// console.log(req.files);
// console.log('Came insode the filter-reports app url >>>>');
// if(done==true){
// console.log(req.files);
// console.log('Files uploaded succesfully ....');
//res.end("File uploaded.");
// }
});
My package structure is like below:
app.js bin node_modules package.json public routes views
My package.json is
{
"name": "nodetest1",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"express": "~4.2.0",
"static-favicon": "~1.0.0",
"morgan": "~1.0.0",
"cookie-parser": "~1.0.1",
"body-parser": "~1.0.0",
"debug": "~0.7.4",
"multer": "~0.1.6",
"jade": "~1.3.0"
}
}
Thanks in advance,
Pradeep
When you pass a folder to Node's require(), it will check for a package.json for an endpoint. If that isn't defined, it checks for index.js, and finally index.node (a C++ extension format). So the index.js is most likely the entry point for requiring a module.
You can check here http://nodejs.org/api/modules.html#modules_folders_as_modules
Usually I use app.js for the application main entry point.
I found the solution. I used the router.use instead of app.use in in the index.js file.