getting the entire error stacktrace in nodejs - node.js

I follow a simple try … catch pattern for my SQLite queries
try {
… run query and get result …
}
catch (error) {
console.log(error);
}
On error, I get a nice stacktrace like this
SqliteError: no such column:
at getData (/Users/punkish/Projects/zenodeo/bin/facets.js:8:25)
at Object.<anonymous> (/Users/punkish/Projects/zenodeo/bin/facets.js:23:1)
at Module._compile (internal/modules/cjs/loader.js:1156:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1176:10)
at Module.load (internal/modules/cjs/loader.js:1000:32)
at Function.Module._load (internal/modules/cjs/loader.js:899:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
at internal/main/run_main_module.js:18:47
I've written my own small logging routine so I can embellish the messages with colors (using chalk) and some extra info I find helpful, now I have
try {
… run query and get result …
}
catch (error) {
mylogger(error);
}
Except, now I just get the following
SqliteError: no such column:
And no, the mylogger is not eating/chopping away the extra bits. I've added the following to it
if (typeof error === 'object') {
log('type: object');
log(`error: ${JSON.stringify(error)}`)
}
and I get
type: object
error: SqliteError: no such column:
Seems like the stacktrace is streaming, and all of it doesn't go to mylogger. In any case, how can I get all of it?

I am using Winston and I encountered the same issue before. I'm using .constructor instead of instanceOf to determine the data type which might be the best practice. But my code here might be of some value to you:
winston​.​format​.​printf​(​info​ ​=>​ {
        ​if​ (​info​.​message​.​constructor​ ​===​ ​Object​ ​||​ ​Error​) {
            ​if​ (​info​.​stack​ ​===​ ​undefined​) {
                ​return​ ​`​${​info​.​timestamp​}​ [​${​info​.​label​}​] ​${​info​.​level​}​: ​${​JSON​.​stringify​(​info​.​message​, ​null​, ​1​)​}​`​;
            } ​else​ {
                ​return​ ​`​${​info​.​timestamp​}​ [​${​info​.​label​}​] ​${​info​.​level​}​: ​${​info​.​message​}​ Stack: ​${​info​.​stack​}​`​;
            }
        } ​else​ {
            ​return​ ​`​${​info​.​timestamp​}​ [​${​info​.​label​}​] ​${​info​.​level​}​: ​${​info​.​message​}​`​;
        }
    })
);

Related

How can I add new field in AssertionError stack when using chai.expect

I am using mocha to build and run multiple test at a time, the below function is responsible for the comparing a message doc I have.
const compareTextWithButtonsMessage = (expected, received) => {
expect(received.title).to.equal(expected.title, 'Title of the text message is not as expected.')
expect(received.subtitle).to.equal(expected.subtitle, 'Subtitle of the message is not as expected.')
expect(received.buttons).to.be.deep.equal(expected.buttons, 'Some properties of buttons of the text message are not as expected.')
}
Whenever there is assertion error the below output is printed on the console:
❯ node msg.test.js
/home/ravi/ori/test/mocha/node_modules/chai/lib/chai/assertion.js:152
throw new AssertionError(
^
AssertionError: Subtitle of the message is not as expected.: expected 'Hope I was able to help you.' to equal 'Hope I have been able to help you.'
at Object.compareTextWithButtonsMessage [as text_with_buttons] (/home/ravi/ori/test/mocha/test/comparators.js:9:34)
at compareMessage (/home/ravi/ori/test/mocha/test/msg.test.js:128:31)
at Object.<anonymous> (/home/ravi/ori/test/mocha/test/msg.test.js:131:1)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
at internal/main/run_main_module.js:17:47 {
showDiff: true,
actual: 'Hope I was able to help you.',
expected: 'Hope I have been able to help you.'
}
The below fields are printed on the console Error message showDiff actual expected.
Now I also want to add one additional field along the error msg stack show my_additional_field. How can I do that? If anyone knows please help me here.

trouble with modules in repl

i am having a hell of time trying to set up a custom repl app. I did a bunch of googling and managed to wrange the code below and got a working repl shell.
script.js
const repl = require("repl")
function evaluate(command, context, filename, callback) {
callback(null, command)
}
repl.start({
prompt: ": ",
eval: evaluate
});
so after getting this prototype working i decided to add a module to split the routing of the command processing. I made a tracker.js module and required it in my script.js
tracker.js
export default class Tracker {
static Process(command) {
console.log(command)
}
}
script.js added the require statement.
const repl = require("repl")
const Tracker = require("./tracker")
function evaluate(command, context, filename, callback) {
callback(null, command)
}
repl.start({
prompt: ": ",
eval: evaluate
});
after i reran this i got an error saying,
SyntaxError: Unexpected token 'export'
at Object.compileFunction (node:vm:352:18)
at wrapSafe (node:internal/modules/cjs/loader:1031:15)
at Module._compile (node:internal/modules/cjs/loader:1065:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (C:\Users\e212034\repository\repl\script.js:2:17)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
PS C:\Users\e212034\repository\repl>
so i went back to google and found some tips saying to add type:module to the package.json. so i did this and reran and now i get this error,
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'C:\Users\e212034\repository\repl\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
at file:///C:/Users/e212034/repository/repl/script.js:1:14
at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:65:12)
PS C:\Users\e212034\repository\repl>
i tried changing the module to .mjs no luck. i tried changing the type to commonjs and the module to .cjs no luck on either.
any ideas on how to resolve this issue?

Is this intended behaviour of custom errors?

I'm currently in the process of remaking the maze package from five years ago in ES2015. I am making a custom error, named LengthError, which will be thrown if an argument of type Function does not have a specified length. I just want to know if this is the intended behaviour because I am running this locally, or if this will carry over to production for when others might use this function?
Error:
LengthError: Argument 'adjacent' must be of length 2
/home/runner/maze/index.ts:6
throw new LengthError('Argument \'adjacent\' must be of length 2')
^
LengthError: Argument 'adjacent' must be of length 2
at null.generate (/home/runner/maze/index.ts:6:13)
at Object.<anonymous> (/home/runner/maze/index.ts:37:1)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47
index.ts:
import { LengthError } from './errors';
export default function generate(nodes: number[], adjacent: Function, choose: Function) {
if (adjacent.length !== 2) {
try {
throw new LengthError('Argument \'adjacent\' must be of length 2')
} catch(e: any) {
console.error(e.name + ': ' + e.message + '\n' + e.stack)
}
}
let node: number = choose(nodes);
let stack = [node];
let maze = new Map();
for (node of nodes) {
maze.set(node, []);
}
while (node) {
let neighbors = nodes.filter(other => !maze.get(other).length && adjacent(node, other));
if (neighbors.length) {
const neighbor = choose(neighbors);
maze.get(node).push(neighbor);
maze.get(neighbor).push(node);
stack.unshift(neighbor);
node = neighbor;
} else {
stack.shift();
node = stack[0];
}
}
return maze;
}
generate([], function a() {}, function b() {});
errors.ts:
class LengthError extends Error {
constructor(message: string) {
super(message);
this.message = message;
this.name = "LengthError";
}
}
export { LengthError };
Again, is this code going to display a similar error in production (where the custom error shows twice) and will it point to the same line in my file?
I just want to know if this is the intended behaviour because I am running this locally, or if this will carry over to production for when others might use this function?
Yes, this is how it works, both locally and in production. This is what nodejs does when there's an uncaught exception using try/catch.
When you throw errors, you're supposed to have code somewhere else that catches them and turns them into the desired behavior.
In the error message, the first line is the statement of the error. The second set of lines are the "stack trace" that show where in the code this originated from, including the current call stack at the time of the error.
Note, in your code that catches exceptions, you may want to log the exception and perhaps even log the track trace and then "handle" the error in some way that makes sense for your application (such as return a user-friendly error message or in an API, return some documented API error or in an http request, return a 4xx or 5xx error status).

googleapis-common throwing error in UUID dependency

I'm trying to get a very basic oauth example to work in a node.js app with express and googleapis. Upon running the application it throws a TypeError inside the UUID dependency which is included with the googleapis-common module. I'm getting a bit frustrated at this point because I have not been able to find any additional information about this to allow me to resolve it myself.
Take a look at the screenshot below for the specifics:
Here it is in text if that makes things easier:
Exception has occurred: TypeError: Cannot assign to read only property 'name' of function 'function generateUUID(value, namespace, buf, offset) {
if (typeof value === 'string') {
value = strin...<omitted>... }'
at _default (C:\Users\ficar\OneDrive\Desktop\Frontend\node_modules\googleapis-common\node_modules\uuid\dist\v35.js:71:23)
at Object.<anonymous> (C:\Users\ficar\OneDrive\Desktop\Frontend\node_modules\googleapis-common\node_modules\uuid\dist\v3.js:14:27)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Module.require (internal/modules/cjs/loader.js:1025:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (C:\Users\ficar\OneDrive\Desktop\Frontend\node_modules\googleapis-common\node_modules\uuid\dist\index.js:63:34)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
The file this is being thrown in is called "v35.js".
My initial thought is that I must be missing some additional library that interprets the logic throwing the error differently. Eager to learn more about this and find a resolution.
Looks like this is how the uuid module works
node_modules/uuid/dist/v35.js
function _default(name, version, hashfunc) {
function generateUUID(value, namespace, buf, offset) {
...
} // Function#name is not settable on some platforms (#270)
try {
generateUUID.name = name; // eslint-disable-next-line no-empty
} catch (err) {} // For CommonJS default export support
...
Authors warn (comment on line 4), that name property may not be settable and bypass it with empty catch

"unexpected token function" error for async, even though node version is 7.6.0+

I'm running out of ideas. I was running node 6.5.0, but then I needed to write some code that has async/await. So I updated node version to 7.7.0 (verified by running node -v) and tried running my app.js again. Unfortunately I'm getting the same error.
Do you have any idea what is happening? I'm running the app with a command node app.js and node -v gives me v7.7.0 response.
I hope I included enough information, please let me know if there's anything I could add to help diagnose this.
Error:
async function navigateWebsite() {
^^^^^^^^
SyntaxError: Unexpected token function
at Object.exports.runInThisContext (vm.js:76:16)
at Module._compile (module.js:528:28)
at Object.Module._extensions..js (module.js:565:10)
at Module.load (module.js:473:32)
at tryModuleLoad (module.js:432:12)
at Function.Module._load (module.js:424:3)
at Module.require (module.js:483:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/home/lucas/app/myapp/app.js:178:19)
at Module._compile (module.js:556:32)`
I'm pasting this function into my app.js application - not sure how code helps if it's clearly an issue with node and not the code.
function test() {
return new Promise(resolve => {
setTimeout(() => {
resolve('test');
}, 2000);
});
}
async function navigateWebsite() {
const msg = await test();
console.log('Message:', msg);
}

Resources