sails-mysql error handling : TypeError: Converting circular structure to JSON - json

Server: Sailsjs
Database: mysql
Node Library used: sails-mysql(0.11.5)
I am trying to insert a data in mysql from sailsjs node server.
Data to be inserted:
{
"first_name": "Admin Testing",
"last_name": "User",
"email": "admin14#testing.com",
"role_id": 8
}
Where role_id is having a foreign key relation to model role.
Here the role_id : 8 doesn't have value in role table. So while inserting, it is throwing the error. But that error we couldn't console or json.stringify since the following error occurs:
TypeError: Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at /var/www/aitachatbot/server/api/controllers/UserController.js:38:42
at wrapper (/var/www/aitachatbot/server/node_modules/waterline/node_modules/lodash/index.js:3602:19)
at applyInOriginalCtx (/var/www/aitachatbot/server/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
at wrappedCallback (/var/www/aitachatbot/server/node_modules/waterline/lib/waterline/utils/normalize.js:331:16)
at error (/var/www/aitachatbot/server/node_modules/switchback/lib/normalize.js:42:31)
at _switch (/var/www/aitachatbot/server/node_modules/switchback/lib/factory.js:56:28)
at /var/www/aitachatbot/server/node_modules/sails-hook-validation/lib/create.js:66:21
at /usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline/query/dql/create.js:223:14
at wrapper (/usr/local/lib/node_modules/sails/node_modules/lodash/index.js:3592:19)
at applyInOriginalCtx (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
at wrappedCallback (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:335:16)
at error (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/normalize.js:42:31)
at _switch (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/factory.js:56:28)
at afterwards (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline/adapter/dql.js:87:16)
at wrapper (/usr/local/lib/node_modules/sails/node_modules/lodash/index.js:3592:19)
at applyInOriginalCtx (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)
at wrappedCallback (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:335:16)
at error (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/normalize.js:42:31)
at _switch (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/switchback/lib/factory.js:56:28)
at sendBackError (/var/www/aitachatbot/server/node_modules/sails-mysql/lib/connections/spawn.js:97:11)
at Object.poolfully [as releaseConnection] (/var/www/aitachatbot/server/node_modules/sails-mysql/lib/connections/release.js:28:12)
at /var/www/aitachatbot/server/node_modules/sails-mysql/lib/connections/spawn.js:90:37
at Query._callback (/var/www/aitachatbot/server/node_modules/sails-mysql/lib/adapter.js:395:27)
at Query.Sequence.end (/var/www/aitachatbot/server/node_modules/sails-mysql/node_modules/mysql/lib/protocol/sequences/Sequence.js:96:24)
at Query.ErrorPacket (/var/www/aitachatbot/server/node_modules/sails-mysql/node_modules/mysql/lib/protocol/sequences/Query.js:94:8)
at Protocol._parsePacket (/var/www/aitachatbot/server/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Protocol.js:280:23)
at Parser.write (/var/www/aitachatbot/server/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Parser.js:73:12)
How can we handle this error in sailsjs?

In theory, you don't want these errors to ever show up in production... even if they did, the full json dump of the error object probably is not something a run-of-the-mill user wants to see.
You may also be asking about how to get full info out of this error while debugging. I guess the good news there is, you seem to already know the root cause of your error!
The error objects we have in node can have pretty different structures depending where they come from, but I have yet to encounter an error that does not have smart casting of the errors to strings. That means that even if console.log(err) fails, something like: console.log('Got an error: ' + err) will likely work, casting the error to a string.
The code could be something like this:
User.create({
"first_name": "Admin Testing",
"last_name": "User",
"email": "admin14#testing.com",
"role_id": 8
}).exec(function(err, createdUser) {
if (err) {
var readableErr = '' + err;
console.log('Error creating user: ' + readableErr);
// return something the client will recognize and interpret
// you can use http error codes, or your own conventions
return res.send({
success: false,
message: readableErr
});
}
// do something with createdUser...
});

Related

Simple React with mySql fails to read table records

I created a React project by entering the following command prompt commands
mkdir mysql-test && cd mysql-test
npm init –y
npm install mysql –save
Then I created a file called app.js and I put in the following code:
// app.js
const mysql = require('mysql');
// First you need to create a connection to the db
const con = mysql.createConnection({
host: 'rds-mysql-wmcw.cgz0te1dlkah.us-east-1.rds.amazonaws.com',
user: 'masterUsername',
password: 'masterPassword',
database : 'db_wmcw'
});
//try to connect to the mySql database. If an error occurs, display an
error message on the console
con.connect((err) => {
if(err){
console.log('Error connecting to Db');
return;
}
//a connection has been established to the database. Now, run a query against the table 'homepage'
//to retrieve each row and all columns of the table
console.log('Connection established');
con.query('SELECT * FROM homepage', (err,rows) => {
//if an error occurs when reading the data from the table, display the error on the console
if(err) {
console.log(err);
return;
}
//data has been retrieved from the table. display the data to the console
console.log('Data received from Db:\n');
console.log(rows);
});
});
con.end((err) => {
// The connection is terminated gracefully
// Ensures all previously enqueued queries are still
// before sending a COM_QUIT packet to the MySQL server.
});
Before I added the con.query command, when I type in app.js at the command prompt, the response back is Connection established. So I know that I am connecting to the mySql database. When I include the con.query command, and I type in app.js at the command prompt, I get the following error:
Connection established
{ Error: Cannot enqueue Query after invoking quit.
at Protocol._validateEnqueue (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\protocol\Protocol.js:203:16)
at Protocol._enqueue (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\protocol\Protocol.js:138:13)
at Connection.query (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\Connection.js:200:25)
at Handshake.con.connect (C:\jrs\codercamp\mysql-test\app.js:21:7)
at Handshake. (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\Connection.js:502:10)
at Handshake._callback (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\Connection.js:468:16)
at Handshake.Sequence.end (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Handshake.Sequence.OkPacket (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\protocol\sequences\Sequence.js:92:8)
at Protocol._parsePacket (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\protocol\Protocol.js:278:23)
at Parser.write (C:\jrs\codercamp\mysql-test\node_modules\mysql\lib\protocol\Parser.js:76:12) code: 'PROTOCOL_ENQUEUE_AFTER_QUIT', fatal: false }
Right at the top of the error it states Cannot enqueue Query after invoking quit. I don't understand why the system thinks I am executing the query after invoking quit. I am not invoking quit unless that is what happens when I execute con.end but con.end is the last statement to execute. It is way after the query call.
Any assistance is greatly appreciated.
Thank you.
PS - I have included the host name, user ID, password, and database name to make debugging easier. There is no real important data in the database
Okay, so the alternative solution would be uninstall mysql package and change with mysql2 package instead. As the author said:
MySQL2 is mostly API compatible with mysqljs and supports majority of features
This answer is for the questioner's comment on his post
If you really wanna reassign the one row of data, you can do:
const { product_detail, product_description } = results[0];
That's basic syntax :D (ES6 maybe)

How can I find which MySQL query is causing errors in my NodeJS app?

I have built an api on top of NodeJS and HapiJS.
The app loads a lot data at startup, and then holds it in memory. I have this app running on a server that has 16 gigs of RAM, so holding 4 gigs of RAM in memory should be possible.
However, every time the app starts up, this error appears 5 times in the log:
{ Error: connect ETIMEDOUT
at Connection._handleConnectTimeout (/home/ec2-user/daemons/liar_lies/node_modules/mysql/lib/Connection.js:425:13)
at Socket.g (events.js:291:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at Socket._onTimeout (net.js:339:8)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5)
--------------------
at Protocol._enqueue (/home/ec2-user/daemons/liar_lies/node_modules/mysql/lib/protocol/Protocol.js:141:48)
at Protocol.handshake (/home/ec2-user/daemons/liar_lies/node_modules/mysql/lib/protocol/Protocol.js:52:41)
at Connection.connect (/home/ec2-user/daemons/liar_lies/node_modules/mysql/lib/Connection.js:136:18)
at /home/ec2-user/daemons/liar_lies/node_modules/knex/lib/dialects/mysql/index.js:106:18
at Promise._execute (/home/ec2-user/daemons/liar_lies/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/home/ec2-user/daemons/liar_lies/node_modules/bluebird/js/release/promise.js:481:18)
at new Promise (/home/ec2-user/daemons/liar_lies/node_modules/bluebird/js/release/promise.js:77:14)
at Client_MySQL.acquireRawConnection (/home/ec2-user/daemons/liar_lies/node_modules/knex/lib/dialects/mysql/index.js:104:12)
at Object.create (/home/ec2-user/daemons/liar_lies/node_modules/knex/lib/client.js:231:16)
at Pool._createResource (/home/ec2-user/daemons/liar_lies/node_modules/generic-pool/lib/generic-pool.js:326:17)
at Pool.dispense [as _dispense] (/home/ec2-user/daemons/liar_lies/node_modules/generic-pool/lib/generic-pool.js:314:12)
at Pool.acquire (/home/ec2-user/daemons/liar_lies/node_modules/generic-pool/lib/generic-pool.js:392:8)
at /home/ec2-user/daemons/liar_lies/node_modules/knex/lib/client.js:281:19
at Promise._execute (/home/ec2-user/daemons/liar_lies/node_modules/bluebird/js/release/debuggability.js:300:9)
at Promise._resolveFromExecutor (/home/ec2-user/daemons/liar_lies/node_modules/bluebird/js/release/promise.js:481:18)
at new Promise (/home/ec2-user/daemons/liar_lies/node_modules/bluebird/js/release/promise.js:77:14)
errorno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
fatal: true }
This is the only error, and it happens 5 times whenever the app starts.
And yet, the app does seem to get most of the data that I expect it to get, so whatever query throws this error, it must be fairly obscure.
How can I figure out which query is the one that throws this error?
The stacktrace does not seem to mention the line in my code that causes this. (I find this frustrating.)
These are the modules that I'm using:
"boom": "3.1.2",
"code": "2.1.0",
"fs": "0.0.2",
"glob": "6.0.4",
"glue": "3.1.0",
"good-console": "5.3.0",
"good-file": "5.1.2",
"hapi": "16.0.2",
"html-entities": "1.2.0",
"joi": "7.2.2",
"knex": "0.12.6",
"knex-logger": "0.1.0",
"multiline": "1.0.2",
"mysql": "2.12.0",
"path": "0.12.7",
"plugo": "0.3.1"
There are only 2 functions that I know of that call the database at startup time. This is one of them:
function build_maps_which_index_database_data(query, which_type_of_data_in_which_database_table) {
DB.knex.raw(query).then(
function(result) {
var count_of_database_results = result[0].length;
build_list_of_allowed_fields(result[0][0]);
for(var how_many_records_processed_so_far = 0; how_many_records_processed_so_far < count_of_database_results; how_many_records_processed_so_far++) {
var document = result[0][how_many_records_processed_so_far];
var profile_id = document['profile_id'];
document['which_type_of_data_in_which_database_table'] = which_type_of_data_in_which_database_table;
document['item_id'] = uuidV4();
build_map_of_uuid_ids_to_documents(document);
Object.keys(document).forEach(function(name_of_field_in_database) {
// avoiding name_of_field_in_database = profile_id
if (name_of_field_in_database != 'profile_id') {
var string_from_database = document[name_of_field_in_database];
build_map_of_santized_words_to_uuid_ids(name_of_field_in_database, string_from_database, document['item_id']);
}
});
}
})
.catch(function(e) {
console.log('Error: calling code was get_map_of_santized_words_to_uuid_ids');
console.log('query was: ' + query);
console.error(e);
});
}
Each of these functions has a "catch" clause attached, so I assume if it was the cause of the error, then I would see that in the log.
Errors in question are not caused by the code that you have included in the question.
To find out what is happening when those errors are sent try to run the app with environment variable DEBUG=knex:*. That will show you what is happening in the connection pool and what queries are sent to DB.
export DEBUG=knex:*
cd ~/yourapp
node server.js
or just
cd ~/yourapp
DEBUG=knex:* node server.js
Also try to remove code from your application until you have minimal amount of code in application, which still produces those errors. After that it should be pretty easy to find the root cause of the problem.
One more thing that you can do is to add debug info to
knex.on('query-error', function (err, obj) { ... });
event and check if that catches those errors.

npm unexpected token / in config.json at position 98

I have seen several unexpected token errors related to npm but this one is yet again unique to me. I could not find any similar issues posted by others. My config file just has connection objects to my local mongodb, rabbitmq "amqp", wordpress plugin and mysql DB.
Could anyone help me with this error in case they've seen it before?
C:\xampp\htdocs\livetrader\chat\node_modules\nconf\lib\nconf\stores\file.js:160
throw new Error("Error parsing your configuration file: [" + this.file + ']: ' + ex.message);
^
Error: Error parsing your configuration file:
[C:\xampp\htdocs\livetrader\chat/config.json]: Unexpected token / in JSON at position 98
Updating this post with the config.json file referenced in this error
{
"port": 1337,
"mongoose": {
"uri": "mongodb://localhost:27017/livetrader"
},
"amqp":{
"uri": "amqp://guest:guest#localhost:15672",
"queue": "TickData"
},
"sql":{
"host":"localhost",
"database":"db_main",
"user":"root",
"password":""
},
"wp":{
"host":"http://forextrader.dev",
"LOGGED_IN_KEY":"MY_LOGGED_IN_KEY",
"LOGGED_IN_SALT":"MY_LOGGED_IN_SALT",
"prefix":"wp_",
"avatarPath":"http://localhost/livetrader/wp-content/uploads/avatars",
"myCreedApi":"MY_API_KEY"
},
"guest":{
"cookie_name": "trading-forex-guest",
"ttl": 180
}
}
Updating the back-end config path
"use strict";
var nconf = require('nconf');
nconf.argv()
.env()
.file({
file: process.cwd() + '/config.json'
});
module.exports = nconf;
Your JSON file is property formatted. JSON.parse() takes it, no problem. Character 98 is not a slash, either.
There is, however, a suspicious slash in your path:
C:\xampp\htdocs\livetrader\chat/config.json
The final slash is unix-style, not windows-style. Could that be causing the problem?
If that's not it, you must be reading the wrong file, or passing it the wrong way to a function. Try using console.log to figure out what exactly is reaching JSON.parse().
Giving objects to JSON.parse() can cause unexpected errors, since .toString() is invoked. For example:
> JSON.parse({a:1})
SyntaxError: Unexpected token o in JSON at position 1
> ({a:1}).toString()
'[object Object]'
So, to recap, you must be:
Reading the wrong file
Passing an object that's not a String to JSON.parse()
Having a strange problem with the inverted slash in the path

Missing exception info in NodeJS JSON.parse

In NodeJS, if I let a JSON.parse exception go unhandled and subsequently crash the server, I get an important bit of information outputted to the console.
My JSON:
{
"familyName": "The Flintstones",
"familyContact": {
"fullName": "Wifie Flintstone",
"contact": {
"street1": "1 Granite Ave",
"city": "Bedrock",
"state": "TX",
"postal": "10000"
}
},
this should make it blow up
"patients": [{
"personInfo": {
"fullName": "Wilma Flintstone"
}}, {
"personInfo": {
"fullName": "Fred Flintstone"
}
}
]
}
This is the console output when I let it go unhandled:
undefined:12
this should make it blow up
^
SyntaxError: Unexpected token t
at Object.parse (native)
at Object.exports.uploadPackage.flowUploads.post.flowUploads.write.onDone (/home/ubuntu/workspace/app/controllers/admin/admin.families.server.controller.js:99:27)
at module.exports.$.write.pipeChunk (/home/ubuntu/workspace/app/services/flowUploads.js:173:49)
at Object.cb [as oncomplete] (fs.js:169:19)
but if I catch the exception to prevent the crash, and log like so...
try{
var fileData = JSON.parse(fileText);
}
catch (ex) {
console.log("REASON FOR JSON FAILURE: " + ex, ex.arguments, ex.stack.split("\n"));
}
I get output like this:
REASON FOR JSON FAILURE: SyntaxError: Unexpected token t [ 't' ] [ 'SyntaxError: Unexpected token t',
' at Object.parse (native)',
' at Object.exports.uploadPackage.flowUploads.post.flowUploads.write.onDone (/home/ubuntu/workspace/app/controllers/admin/admin.families.server.controller.js:100:27)',
' at module.exports.$.write.pipeChunk (/home/ubuntu/workspace/app/services/flowUploads.js:173:49)',
' at Object.cb [as oncomplete] (fs.js:169:19)' ]
Missing that key piece of useful info from the crash log that contains the line number and snip of faulty text:
undefined:12
this should make it blow up
^
How I can get to that bit so I can include it in my error messaging?
You can't get that first bit you displayed from the error since it isn't part of the error.
undefined:12
this should make it blow up
^
This is because node is adding that section before dying to show why it died and then shows the error generated by JSON.parse.
To get more detailed messaging you will have to use something other then JSON.parse. As robertklep mentioned you could try greatjson or something similar if getting greater detail on your JSON parsing is important, such as if you are building a service which parses JSON and returns the errors.

Sails.JS + MySQL: Unknown column 'NaN' in 'where clause'

this is my first time using sails.js with mySQL database and I'm really confused about this error.
I have a controller & model called 'company'. It relates to table 'company' in mySQL database. The table itself has one-to-many associations with two tables called 'module' and 'user' (each user/module must connect with one company id). I've set the foreign key in the MySQL database.
The problem is.. each time I open any page/action from this controller, there is this error:
error: Sending 500 ("Server Error") response:
Error (E_UNKNOWN) :: Encountered an unexpected error
: ER_BAD_FIELD_ERROR: Unknown column 'NaN' in 'where clause'
at Query.Sequence._packetToError (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/sequences/Sequence.js:30:14)
at Query.ErrorPacket (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/sequences/Query.js:82:18)
at Protocol._parsePacket (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Protocol.js:213:24)
at Parser.write (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Parser.js:62:12)
at Protocol.write (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Protocol.js:37:16)
at Socket.<anonymous> (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/Connection.js:75:28)
at Socket.emit (events.js:95:17)
at Socket.<anonymous> (_stream_readable.js:764:14)
at Socket.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:426:10)
--------------------
at Protocol._enqueue (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Protocol.js:110:48)
at PoolConnection.Connection.query (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/Connection.js:166:25)
at PoolConnection.liveConnection.query (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/lib/connections/spawn.js:98:16)
at __FIND__ (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/lib/adapter.js:836:20)
at afterwards (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/lib/connections/spawn.js:104:5)
at /Users/alanyudh/Sites/matta/node_modules/sails-mysql/lib/connections/spawn.js:40:7
at Pool.<anonymous> (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/Pool.js:51:14)
at Handshake.Sequence.end (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/sequences/Sequence.js:78:24)
at Handshake.Sequence.OkPacket (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/sequences/Sequence.js:87:8)
at Protocol._parsePacket (/Users/alanyudh/Sites/matta/node_modules/sails-mysql/node_modules/mysql/lib/protocol/Protocol.js:213:24)
Details: Error: ER_BAD_FIELD_ERROR: Unknown column 'NaN' in 'where clause'
This is my company model:
module.exports = {
attributes: {
name:{
type:"string",
required:true,
unique:true,
minLength: 2
},
type:{
type:"string",
enum: ['hq','sub'],
defaultsTo: 'hq'
},
desc:{
type:"text",
required:true
},
logo: {
type: 'string'
},
address: {
type: 'text'
},
city: {
type: 'string'
},
region: {
type: 'string'
},
country: {
type: 'string'
},
zipcode: {
type: 'string'
},
phone_number: {
type: 'string'
},
website: {
type: 'string'
}
},
};
I have tried using 'autoPK: false', 'schema: true', add 'columnName/fieldName', but none of them is working.
What is the error means?
How do I fix it?
Thank you very much.
Oppening localhost:1337/company/index is your problem not any mysql or other orm problem!
This is a route config probem. When you open this URL the default sails behavior is that you try to access a specific company record through the default REST api. Check the default rest routes behavior.
To be more explicit in your case sails interpret that you are querying a specific company with the id "index" which is not a number NaN thus you get this error.
RESTful routes, where the path is always /:modelIdentity or /:modelIdentity/:id.
I do NOT have the exact answer, to your specific case, BUT, I need to point to you and at the same time ventilate here my frustration, that it is a pathetic notorious problem of various APIs, when they do not address the cause of an error specifically enough, and just let the exception stack lazily bubble out to the next error handler. This often will be completely misleading the developer about the cause of the actual exception. So be VERY mindful that the error text you see may be pretty much OFF the actual issue. Well, at least you know there is a problem. Now you have to use your own wits and endless variations or approaches to figure it out.