Node.js Mongoose PUT Failed - node.js

I am trying to PUT mongoose data using postman but it shows "TypeError: bear.save is not a function" in server console and crash the node app.
In this problem I am running two apps on different ports and db with the same code, normal http app can make all requests(POST,PUT,DEL,GET) success but another https app can't make PUT request, it can only make POST and GET successfully .
I can't understand why the same code on http app not showing error if it was code problem. Please help me.
REST API reference from - Here
.get(function(req, res) {
Bear.find( {ID: req.params.bear_id} , function(err, bear) {
if (err)
res.send(err);
res.jsonp(bear);
});
})
.put(function(req, res) {
Bear.find( {ID: req.params.bear_id}, function(err, bear) {
if (err)
res.send(err);
bear.Name = req.body.Name;
//res.json(bear) can send data up to this line
// save the bear (crash after following line)
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear updated!' });
});
})
});
Error Log on console -
TypeError: bear.save is not a function
at Promise.<anonymous> (/var/www/vhosts/mydomain.com/nodeapp.js:130:18)
at Promise.<anonymous> (/var/www/vhosts/mydomain.com/node_modules/mpromise/lib/promise.js:162:8)
at emitOne (events.js:96:13)
at Promise.emit (events.js:188:7)
at Promise.emit (/var/www/vhosts/mydomain.com/node_modules/mpromise/lib/promise.js:79:38)
at Promise.fulfill (/var/www/vhosts/mydomain.com/node_modules/mpromise/lib/promise.js:92:20)
at /var/www/vhosts/mydomain.com/node_modules/mongoose/lib/query.js:1736:26
at model.Document.init (/var/www/vhosts/mydomain.com/node_modules/mongoose/lib/document.js:251:11)
at completeMany (/var/www/vhosts/mydomain.com/node_modules/mongoose/lib/query.js:1734:12)
at cb (/var/www/vhosts/mydomain.com/node_modules/mongoose/lib/query.js:1697:11)

You probably want to use findOne instead of find.

Related

unable to change password using mongoose

I am using MongoDB, mongoose, ejs and NodeJS for my site. I have a update password function which is not working properly. I have checked again and again by login different things in console and there is no problem in getting data in req. So I guess my problem is in the controller. This is my controller:
module.exports.update_password = function (req, res) {
console.log(req.user);
Company.findOne({ username: req.user.username }, function (err, user) {
if (user.password == req.body.current_password) {
if (req.body.new_password == req.body.confirm_password) {
Company.findOneAndUpdate({ username: req.user.username }, { password: req.body.new_password }, { upsert: true }, function (err, doc) {
if (err) return res.send(500, { error: err });
req.flash('notify', 'Password changed!')
return res.redirect('/profile');
});
}
else req.flash('notify', 'New password does not match with confirm password');
}
else req.flash('notify', '!')
});
return res.redirect('/profile');
}
everytime updating my password I get this error:
node:events:355
throw er; // Unhandled 'error' event
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:329:5)
at ServerResponse.setHeader (node:_http_outgoing:573:11)
at ServerResponse.header (/home/krush/github/Project_Lightspeed/node_modules/express/lib/response.js:771:10)
at ServerResponse.location (/home/krush/github/Project_Lightspeed/node_modules/express/lib/response.js:888:15)
at ServerResponse.redirect (/home/krush/github/Project_Lightspeed/node_modules/express/lib/response.js:926:18)
at /home/krush/github/Project_Lightspeed/controllers/authentication_controller.js:45:32
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4857:16
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4857:16
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/helpers/promiseOrCallback.js:24:16
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4880:21
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/query.js:4397:11
at /home/krush/github/Project_Lightspeed/node_modules/kareem/index.js:136:16
at processTicksAndRejections (node:internal/process/task_queues:76:11)
Emitted 'error' event on Function instance at:
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/model.js:4859:13
at /home/krush/github/Project_Lightspeed/node_modules/mongoose/lib/helpers/promiseOrCallback.js:24:16
[... lines matching original stack trace ...]
at processTicksAndRejections (node:internal/process/task_queues:76:11) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
It seems that the problem is that the return res.redirect('/profile'); command is executed before your callback functions. Which is normal since this is how the event loop works.
Try to remove the return res.redirect('/profile'); line to see if the error goes away. Callbacks at node.js execute at a later stage of the event loop.
Generally I would recommend to refactor your code to use promises instead of callbacks since that causes the "callback hell" anti-pattern.
If you refactor your code to use promises, then you will be able to use .then or async await, which will help you write cleaner code and help you spot any error easily.

Cannot set headers after they are sent to the client - Node/Mongoose/Express

I am working on an fantasy soccer app for my friends and I, but I am getting this age old error and it doesn't seem like any of the other questions answered on here really fit my situation. In the first block of code below, the console.log is returning the correct data, so I am very certain that the res.json(populatedClub) should be working just fine. I cannot find anywhere else in my code that is triggering another res.send() or res.json() in this chain of events.
Is anybody else able to see what I am not?
My route:
fantasyClubRouter.get('/:userId',
(req, res) => {
FantasyClub
.findOne({manager: req.params.userId})
.populate({
path: 'manager',
model: 'User'
})
.exec((error, populatedClub) => {
if (error) {
return () => {throw new Error(error)};
}
console.log('populatedClub:', populatedClub);
res.json(populatedClub);
})
.catch(error => {
throw new Error(error);
});
}
);
The error stack:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:471:11)
at ServerResponse.header (/home/ubuntu/workspace/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/home/ubuntu/workspace/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/home/ubuntu/workspace/node_modules/express/lib/response.js:267:15)
at FantasyClub.findOne.populate.exec (/home/ubuntu/workspace/server/fantasyClub-routes.js:18:11)
at /home/ubuntu/workspace/node_modules/mongoose/lib/model.js:4187:16
at (anonymous function).call (/home/ubuntu/workspace/node_modules/mongoose/lib/query.js:3128:7)
at process.nextTick (/home/ubuntu/workspace/node_modules/mongoose/lib/query.js:2019:28)
at process._tickCallback (internal/process/next_tick.js:61:11)
Emitted 'error' event at:
at /home/ubuntu/workspace/node_modules/mongoose/lib/model.js:4189:13
at (anonymous function).call (/home/ubuntu/workspace/node_modules/mongoose/lib/query.js:3128:7)
at process.nextTick (/home/ubuntu/workspace/node_modules/mongoose/lib/query.js:2019:28)
at process._tickCallback (internal/process/next_tick.js:61:11)
I figured out what I had done wrong, and it was so simple that I'm almost embarrassed to admit it, but here it goes.
I updated from an older version of Mongoose and forgot to update my code accordingly. Always make sure your code matches what the docs say for the version of the library you are using.
This is the working code:
fantasyClubRouter.get('/:userId',
(req, res) => {
FantasyClub
.findOne({manager: req.params.userId})
.populate({
path: 'manager',
model: 'User'
})
.then(populatedClub => {
res.json(populatedClub);
})
.catch(error => {
throw new Error(error);
});
}
);

NodeJS -> Error: write after end (only after first request)

In my express app i have the route below:
router.get('/generatedData', function (req, res) {
res.setHeader('Connection' , 'Transfer-Encoding');
res.setHeader('Content-Type' , 'text/html; charset=utf-8');
res.setHeader('Transfer-Encoding' , 'chunked');
var Client = someModule.client;
var client = Client();
client.on('start', function() {
console.log('start');
});
client.on('data', function(str) {
console.log('data');
res.write(str);
});
client.on('end', function(msg) {
client.stop();
res.end();
});
client.on('err', function(err) {
client.stop();
res.end(err);
});
client.on('end', function() {
console.log('end');
});
client.start();
});
On first call everything works fine (console)
We've got ourselves a convoy on port 3000
start
data
data
data
data
data
...
data
end
GET /generatedData 200 208.426 ms - -
I get all the data and res.end() is being called and successfully closes the request.
The problem starts after first request. I make the exact same request (new one of course) and i get the following error (console):
start
data
data
data
events.js:160
throw er; // Unhandled 'error' event
^
Error: write after end
at ServerResponse.OutgoingMessage.write (_http_outgoing.js:439:15)
at Client.<anonymous> (/Users/xxxx/projects/xxxx/routes/index.js:33:17)
at emitOne (events.js:96:13)
at Client.emit (events.js:188:7)
at FSWatcher.<anonymous> (/Users/xxxx/projects/xxxx/lib/someModule.js:116:32)
at emitTwo (events.js:106:13)
at FSWatcher.emit (events.js:191:7)
at FSEvent.FSWatcher._handle.onchange (fs.js:1412:12)
[nodemon] app crashed - waiting for file changes before starting...
This happens without res.end() being called.
I manage to get some data before the crash.
How can i get this error without res.end() being called at all?
Do i somehow save the previous res instance?
Thanks,
Asaf
Have the same problem. My module was extened by EventEmitter and each time i catch event in router - it stays there, end on second call there are two eventlisteners not one. Setting "once" instead of "on" - worked for me.
client.once('start', function() {
console.log('start');
});
instead of
client.on('start', function() {
console.log('start');
});

Error using Redis Multi with nodejs

I am using Redis and consulting it from nodejs, using the module Redis.
When i exec a client.multi() and the redis server is down the callback doesn't send the error and the nodejs app terminates.
This is the error
/Users/a/db/node_modules/redis/index.js:151
throw callback_err;
^
TypeError: Cannot read property 'length' of undefined
at Command.callback (/Users/a/db/node_modules/redis/index.js:1098:35)
at RedisClient.flush_and_error (/Users/a/db/node_modules/redis/index.js:148:29)
at RedisClient.on_error (/Users/a/db/node_modules/redis/index.js:184:10)
at Socket.<anonymous> (/Users/a/db/node_modules/redis/index.js:95:14)
at Socket.EventEmitter.emit (events.js:95:17)
at net.js:441:14
at process._tickCallback (node.js:415:13)
this is my code:
Constructor class
var redis = require('redis');
var client;
function Redis(){
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err);
});
}
Redis.prototype.multi = function(commands,callback){
var err = null;
client.multi(commands).exec(function (error, res) {
if(error){
process.nextTick(function(){
callback(error,null)
})
}else{
process.nextTick(function(){
callback(null,res)
})
}
});
}
FYI, I ran across this in an old lib that depended on old version of node_redis.
This issue was a bug and was fixed in v0.9.1 - November 23, 2013: https://github.com/mranney/node_redis/pull/457
I think that people are still reaching here... (not sure if this answers this specific question directly, but I assume people reaching here since the multi.exec() returns true / the event loop is not waiting for it's response.
After the fixes that went in (in node-redis), it is possible to wrap the result of exec with Promise, and then you will be sure that the result will include the replies from the multi.
So, you can add some redis commands to the multi:
await multi.exists(key);
await multi.sadd(key2,member);
And then in the result do something like:
return new Promise((resolve, reject) => {
multi.exec((err, replies) => {
if (err) {
reject(err);
}
return resolve(replies);
});
});
Otherwise, if you will just do: const reply = await multi.exec();
it will just return you true, and not the replies
** Important to mention - this refers to 'async-redis' and 'node-redis'

NodeJS: installed cradle 5.5 but example crashes with error

var cradle = require('cradle');
var db = new(cradle.Connection)().database('starwars');
db.get('vader', function (err, doc) {
doc.name;
assert.equal(doc.force, 'dark');
});
db.save('skywalker', {
force: 'light',
name: 'Luke Skywalker'
}, function (err, res) {
if (err) {
// Handle error
} else {
// Handle success
}
});
installed cradle via npm
npm install cradle
The error output running node cradle.js
root#server:~# node cradle.js
/root/cradle.js:5
doc.name;
^
TypeError: Cannot read property 'name' of undefined
at Object.callback (/root/cradle.js:5:8)
at /root/node_modules/cradle/lib/cradle.js:276:26
at IncomingMessage.<anonymous> (/root/node_modules/cradle/lib/cradle.js:210:21)
at IncomingMessage.emit (events.js:81:20)
at HTTPParser.onMessageComplete (http.js:133:23)
at Socket.ondata (http.js:1213:22)
at Socket._onReadable (net.js:681:27)
at IOWatcher.onReadable [as callback] (net.js:177:10)
UPDATE: problem boils down to
db.get('vader', function (err, doc) {
doc.name;
assert.equal(doc.force, 'dark');
});
it's complaining about doc.name
Where can I view the database so I can see the new row added?
db.get('vader', function (err, doc) {
if (err) {
console.log(err);
} else {
doc.name;
assert.equal(doc.force, 'dark');
}
});
The example doesn't do error handling. I would assume the error is document vader doesn't exist or database starwars doesn't exist.
If you have couch installed and running then the database lives at http://localhost:5984/_utils/

Resources