Why is a successful update response always passed as an error. is something wrong with my code or is it the Mongo DB response.
However I don't see any errors when I check them on MongoDB.
MongoDB Enterprise > db.getLastError();
null
Response:
{
"lastErrorObject": {
"n": 1,
"updatedExisting": true
},
"value": {
"_id": "1111111111",
"xyz": "hgfjdfjk"
}
}
Code Block
{
try {
const db = client.db(dbName);
db.collection(cName).updateOne({ _id: id }, { $pull: query }).then((err, result) => {
if (err) {
callBack(err);
} else {
callBack(null, result);
}
});
client.close();
}
catch (err) {
callBack({
error: 'Unable to process the request',
errorMessage: err
})
}
}
getLastError() returns the server response to the current operation within that connection, and is not related to an actual error in MongoDB. It is part of MongoDB's wire protocol.
See getLastError for more details.
Related
I'm currently working on the freeCodeCamp Exercise Tracker Project on Replit.
my Project Link: https://replit.com/#mazorSharp/Exercise-Tracker?v=1
If you click on the link, the code I'm referring to is in the server.js file and It's the code under the comment labeled // NUMBER 3
I'm running into an issue with one of the GET routes.
GET user's exercise log: GET /api/users/:_id/logs?[from][&to][&limit]
The GET route works fine when all queries are used in the get search. Queries for the test are From, To, and Limit. If one of the queries aren't present in the GET request I get an error.
CastError: Cast to date failed for value "Invalid Date" (type Date) at path "date" for model "exerciseInfo"
What steps would I need to take to make sure if someone isn't putting in values for FROM, TO, and LIMIT queries that it wouldn't throw an error because of it?
app.get('/api/users/:_id/logs', (req, res) => {
const {from, to, limit} = req.query;
let idJson = {"id": req.params._id}
let idToCheck = idJson.id;
console.log("from=> ", from, "to=> ", to, "limit=> ", limit, "idToCheck=> ", idToCheck);
//Check ID
ExerciseInfo.findById(idToCheck, (err, data) => {
if (err) {
console.log("Error with ID => ", err);
} else {
// Find Username Documents
ExerciseInfo.find(({username: data.username}, {date: {$gte: new Date(from), $lte: new Date(to)}}), null , {limit: +limit} , (err, doc) => {
let loggedArray = []
if (err) {
console.log("error with username=> ", err);
} else {
console.log("all docs related to username=> ", doc);
let documents = doc;
let loggedArray = documents.map((item) => {
return {
"description": item.description,
"duration": item.duration,
"date": item.date.toDateString(),
}
})
const test = new LogInfo({
// "_id": idToCheck,
"username": data.username,
"from": from,
"to": to,
"count": limit,
"log": loggedArray,
})
test.save((err, data) => {
if (err) {
console.log(err);
} else {
console.log("saved exercise successfully")
res.json({
"_id": idToCheck,
"username": data.username,
"from": data.from.toDateString(),
"to": data.to.toDateString(),
"count": data.count,
"log": loggedArray,
})
}
})
}
})
}
})
})
I was starting with GraphQL and I was unable to comprehend how we can throw errors in GraphQL
I went through a couple of articles on the web but almost all of them use Apollo and the code-structure looks very different than how I work.
Consider this piece of code, here where I am making a mutation, now how can send a response message with error and change headers status message in case of error?
AddNewPersonalInfo: {
type: userDashboardType,
args: {
parameter: {
type: userCreationlInputType
}
},
resolve: async (parent, args, context) => {
args.parameter.userId = context.req.headers.userId
//Check if user info already exsist
const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
if (checkIfUserInformationExsist[0]) {
const error = {
code: 403,
message: 'User info Already exsist'
}
throw new Error(error)
} else {
try {
const addLinkedinUser = await insertIntheTable('personal', payload)
return true
} catch (err) {
console.error(err)
throw new Error(err)
}
}
}
}
What I have faced in one of my projects, it is hard to set the status code of the response. So, I made some custom error response to identify correct statusCode using express-graphql
Below is the example (What I have used in one of my projects):
--------app.js file--------
const graphqlHTTP = require('express-graphql')
app.use('/graphql', (req, res) => {
graphqlHTTP({
schema: GraphQLSchema, //A GraphQLSchema instance from GraphQL.js. A schema must be provided.
graphiql: true,
context: { req },
formatError: (err) => {
const error = getErrorCode(err.message)
return ({ message: error.message, statusCode: error.statusCode })
}
})(req, res)
})
--------getErrorCode function implementation--------
const { errorType } = require('../constants')
const getErrorCode = errorName => {
return errorType[errorName]
}
module.exports = getErrorCode
--------Constant.js file--------
exports.errorName = {
USER_ALREADY_EXISTS: 'USER_ALREADY_EXISTS',
SERVER_ERROR: 'SERVER_ERROR'
}
exports.errorType = {
USER_ALREADY_EXISTS: {
message: 'User is already exists.',
statusCode: 403
},
SERVER_ERROR: {
message: 'Server error.',
statusCode: 500
}
}
Now, we are ready to use our setup.
From your query or mutation, you need to require constant file and return custom error:
const { errorName } = require('../constant')
AddNewPersonalInfo: {
type: userDashboardType,
args: {
parameter: {
type: userCreationlInputType
}
},
resolve: async (parent, args, context) => {
args.parameter.userId = context.req.headers.userId
//Check if user info already exsist
const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
if (checkIfUserInformationExsist[0]) {
const error = {
code: 403,
message: 'User info Already exsist'
}
throw new Error(errorName.USER_ALREADY_EXISTS) // Here you can use error from constatnt file
} else {
try {
const addLinkedinUser = await insertIntheTable('personal', payload)
return true
} catch (err) {
console.error(err)
throw new Error(errorName.SERVER_ERROR) // Here you can use error from constatnt file
}
}
}
}
--------Error response--------
{
error: [{
"statusCode": 403,
"message": "User is already exists."
}],
data: null
}
We just need to write custom error handling from FS side too.
Note:- formatError: is deprecated and replaced by customFormatErrorFn. It will be removed in version 1.0.0. You can refer customFormatErrorFn.
graphql should be an application level layer that shouldn't (see last paragraph why shouldn't and not doesn't) require http to work. Although in 99% of cases it runs on top of http, because of how convenient it is to do so, graphql is itself a layer 7 protocol.
What does that mean in your case? Well, it means you should not mix concepts from HTTP/REST with concepts from graphql and focus on the latter. The headers error code is a HTTP/REST concept, graphql sends errors in the errors field of the response and the nodejs implementation already catches all your errors and adds them to the list. The HTTP status will be always 200, and your clients shouldn't care and consume your graphql api and not a mix of REST with graphql.
That being said, there are couple of things that REST over HTTP does better. So people, including the developers of Apollo, kinda mixed concepts too, mainly because the graphql standard is not complete (aka, it doesn't have a standard/rule for solving all the problems you might encounter while building an API), so people improvised. I wouldn't recommend graphql yet for any serious project.
Reference
You can specify an error function inside graphqlHTTP like this:
app.use("/graphql", graphqlHTTP({
schema,
graphiql: true,
customFormatErrorFn: err => {
try {
err.details = JSON.parse(err.message);
err.message = Array.isArray(err.details.error) ? err.details.error.join(",") : err.details.error;
return err;
} catch {
return err;
}
}
}));
where err.message might contain a JSON object or a string.
you can use those function to generate specific client and server error functions:
const clientError = error => new Error(JSON.stringify({
success: false,
code: 400,
error
}));
const serverError = ({ name, message, stack }) => new Error(JSON.stringify({
success: false,
error: "Server Error",
code: 500,
name,
message,
stack
}));
const userValidationError = err => {
if (err.name === "ValidationError") return clientError(Object.values(err.errors).map(({ message }) => message));
return serverError(err);
}
module.exports = {
clientError,
serverError,
userValidationError
};
userValidationError function is useful if you have a mongodb validation error.
so that you would use it inside resolve function like this:
try {
const createdDocument = await MongooseDoc.create(data);
return createdDocument;
} catch (err) {
throw userValidationError(err);
}
the response would be
{
"errors": [
{
"message": "error details 1,error details 2",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"document"
],
"details": {
"success": false,
"code": 400,
"error": [
"error details 1",
"error details 2"
]
}
}
],
"data": {
"document": null
}
}
if you want to throw a clientError you throw it outside try catch.
Hopefully this code helps someone send dynamic error messages in graphql.
I am trying to upload some data to my MongoDB from a Node.js script, at the moment it will upload about 5 sets of data and return this error:
MongoError: E11000 duplicate key error collection: database.customers index: _id_ dup key: { : ObjectId('5cf7a6e9b4957b3848e7cac4') }
I think this is due to some data records in my JSON being the same (specifically the process), however this isn't an issue.
I have tried to use the .createIndex() function however I am not too sure how to fully integrate that with my .insertOne() function.
data= {
'Process': varprocess,
'Number' : idnumber,
}
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydatabase");
dbo.collection("customers").insertOne(data, function(err, res) {
if (err) throw err;
console.log("1 document inserted");
db.close();
});
});
{
"data": [
{
"Process": "Process1",
"Number": "00000",
},
{
"Process": "Process1",
"Number": "00001",
}
]
}
I am expecting it to upload data regardless of duplicates, as you can see it doesn't like 'Process1' being entered more than once. What can I do so that all of my data is sent to the DB without errors?
thanks
I'm trying to do a search quest using js-zimbra module, i keep on getting an error that i didn't knew how to fix,
her's my code :
var z = require('js-zimbra');
var comm = new z.Communication({
url: "myzimbraurl/service/soap"
});
// Authenticate
comm.auth({
"username": "user",
"secret": "pass",
"isPassword": true
}, function(err) {
if (err) {
// An error occured authenticating!
}
console.log('done !')
// Now, carry on creating requests and sending them
comm.getRequest({}, function(err, req) {
if (err) {
// Can't create a new request
}
req.addRequest({
name: "SearchRequest",
namespace: "zimbraMail",
params: {
"SearchRequest" : {
"types" : "message",
"fetch" : "all"
},
"query": {
"_content": "in:inbox"
}
}
}, function(err) {
if (err) {
console.log('err', err);
}
comm.send(req, function(err, res) {
if (err) {
console.log('err', err);
}
console.log(res);
})
})
})
});
and when i execute i got the following error message :
error: Received server error: {"Code":{"Value":"soap:Receiver"},"Reason":{"Text":"error while proxying request to target server: Connection reset"},"Detail":{"Error":{"Code":"service.PROXY_ERROR","Trace":"","_jsns":"urn:zimbra"}}}
Is there any fix for such error ?
For some reason that I cannot seem to wrap my brain around, whenever I send an Object over the network, its parameters change from when I send the Object over the network from the server to when I read it back on the client.
Here's the scenario:
I'm testing an API to delete your user account from the database. You send over your authToken and username parameters in a specially formatted Object, the server queries the database, and if found, your user account is deleted. When everything works perfectly, your account, the server sends this string back to you:
{ header: { type: 'success' }, body: {} }
That's known as a plain SuccessEnvelope. However, when I read the returned string from the server, I get this:
{ header: { type: 'error' }, body: {} }
Now, it seems that the type parameter is being changed somewhere, but I have no idea where! Below you'll find the relevant code which handles all of these requests:
server.js
server = net.createServer(function(socket) {
socket.on("data", function(data) {
try {
// Accept Envelope from client
var input = new Envelope(data.toString());
if (input.verify()) { // Make sure client Envelope has correct data
switch (input.header.type) { // Route commands based on Envelope "type"
case "user":
userHandler.parseEnvelope(input, function(err, res) {
if (err) {
socket.write(errors.parseError(err).toString());
} else {
socket.write(res.toString());
}
});
break;
default:
socket.write(new Envelope().toString());
break;
}
} else {
socket.write(errors.parseError(
new errors.MissingHeaderDataError()).toString());
}
} catch (err) {
socket.write(errors.parseError(err).toString());
}
});
});
user-handler.js
// removing some of the unnecessary stuff
case "delete":
// Make sure user provided all necessary information.
if (!header.token || !body.username) {
return callback(new errors.MissingEnvelopeDataError("Missing the 'token' and/or
'username' parameter(s) in header and/or body, respectively"));
} else {
// Delete the user's account. So sad to see them go... :'(
User.findOne({"token": header.token, "username": body.username}, "+token +_id",
function(err, user) {
if (err) {
return callback(err);
} else {
user.remove(function(err) {
if (err) {
return callback(err);
} else {
// Everything went according to plan. Return a SuccessEnvelope to the user.
callback(new SuccessEnvelope());
}
});
}
});
}
break;
Can anyone see what I did wrong? Any help would be fantastic. Thanks in advance!
EDIT: It's probably also a good idea to include my test cases...
deleteUser = {
"header": {
"type": "user",
"method": "delete",
"token": ""
},
"body": {
"username": ""
}
}
describe("Delete user", function() {
it("should return a MissingEnvelopeDataError when deleting a user without a token or
username", function(done) {
connection.write(JSON.stringify(deleteUser));
connection.on("data", function(res) {
res = JSON.parse(res.toString());
res.header.should.have.property("type", "error");
res.header.should.have.property("errorType", "MissingEnvelopeDataError");
done();
});
});
it("should return a SuccessEnvelope when deleting a user", function(done) {
deleteUser.header.token = user.token;
deleteUser.body.username = user.username;
connection.write(JSON.stringify(deleteUser));
connection.on("data", function(res) {
res = JSON.parse(res.toString());
console.dir(res);
res.header.should.have.property("type", "success");
// res.body.should.be.empty
(function() {
if (Object.keys(res.body).length == 0) {
return true;
} else {
return false;
}
})();
done();
});
});
});
The user variable you see here is just a simple object, which stores all of the user info.
As usual, I'm an idiot and don't follow my own API.
The callback function that's being passed takes two parameters: err and response. I was forgetting to pass null as my error, so the code was doing exactly what it should have been doing. DOH! Thanks for the responses, everyone!