'Stack trace with fs/promises and async..await
I have a problem that is similar to this one and described in this issue. There are no stack traces in errors that come from fs/promises when used with async..await, and no way to determine where the error happened.
Given the app:
foo.js
const { bar } = require('./bar');
async function foo() {
await bar();
}
(async () => {
await foo();
})().catch(console.error);
bar.js
const fs = require('fs/promises');
exports.bar = async function bar() {
await fs.readFile('some');
}
When it runs like node foo.js, this results in an error with no stack trace:
[Error: ENOENT: no such file or directory, open '...\some'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: '...\\some'
}
Where error.stack contains 'ENOENT: no such file or directory, open '...\some'.
When it runs like node --stack_trace_limit=100 -r trace foo.js with trace package, like it's suggested in linked sources, this results in this stack trace:
Notice that internal entries are grayed and can be filtered out.
This node --stack_trace_limit=100 -r trace -r clarify foo.js with trace and clarify packages results in this output:
Error: ENOENT: no such file or directory, open '...\some'
at ...\foo.js:8:2
at Object.<anonymous> (...\foo.js:10:3) {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: '...\\some',
[Symbol(originalCallSite)]: [],
[Symbol(mutatedCallSite)]: [ CallSite {}, CallSite {} ]
}
The problem is that bar.js isn't mentioned in all of the outputs.
My intention is to provide clean error output with no internal entries and the exact location where the error occurs, i.e. line number in bar.js.
What are possible solutions to this problem?
Solution 1:[1]
So close :)
Edit: based on fs/promise issue, it's a known issue, and could be worked-around on demand, as suggested below.
This node --stack_trace_limit=100 -r trace -r clarify foo.js with trace and clarify packages results in this output:
Error: ENOENT: no such file or directory, open '...\some' at ...\foo.js:8:2 at Object. (...\foo.js:10:3) {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: '...\some',
[Symbol(originalCallSite)]: [],
[Symbol(mutatedCallSite)]: [ CallSite {}, CallSite {} ]
}The problem is that bar.js isn't mentioned in all of the outputs.
In addition for using trace/clarify, do try/catch directly on fs.readFile call (bar.js)
const fs = require('fs/promises');
exports.bar = async () => {
try {
await fs.readFile('some');
} catch (e) {
console.error(e);
}
}
$ node --stack_trace_limit=100 -r trace -r clarify foo.js
Error: ENOENT: no such file or directory, open 'some'
at emitInitNative (node:internal/async_hooks:205:43)
at emitInitNative (node:internal/async_hooks:205:43)
at emitInitScript (node:internal/async_hooks:495:3)
at promiseInitHook (node:internal/async_hooks:325:3)
at promiseInitHookWithDestroyTracking (node:internal/async_hooks:329:3)
at Object.readFile (node:internal/fs/promises:786:24)
at exports.bar (/home/lz/code/stackover/bar.js:6:18)
at foo (/home/lz/code/stackover/foo.js:4:11)
at /home/lz/code/stackover/foo.js:9:15
at Object.<anonymous> (/home/lz/code/stackover/foo.js:13:3)
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 {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: 'some'
}
You can also try sync read file.
Solution 2:[2]
Since the root cause of your problem is that fs/promises Errors have no stack by design, why simply not throwing your own when you need stack details?
More than this I can suggest to avoid using the catch method of promises and to use only the async/await construct.
foo.js
const { bar } = require('./bar');
async function foo() {
await bar();
}
(async function main() {
try {
await foo();
} catch(e) {
console.error(e);
}
})();
bar.js
const fs = require('fs/promises');
exports.bar = async function bar() {
try{
await fs.readFile('some');
} catch(e) {
throw new Error(e.message);
}
};
This gives following result:
Error: ENOENT: no such file or directory, open 'some'
at bar (/home/me/test/bar.js:7:11)
at async foo (/home/me/test/foo.js:4:3)
at async main (/home/me/test/foo.js:9:5)
Probably you neither need to use trace and/or clarify, but of course you are still free to use them to alter the stack trace at your needs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |

