help icon indicating copy to clipboard operation
help copied to clipboard

How to tell the real source of an error in a callback?

Open ugultopu opened this issue 5 years ago • 3 comments

I'm trying to use a function as a callback in possibly multiple places. However, I can't figure out how to make the callback function tell me the real source of the error.

// `throwIfError` is a function that could be used as a callback
// in multiple places.
function throwIfError(err) {
  if(err) {
    // Some code that will tell me that the error originated from a call
    // to `fs.writeFile` in this file (that is, line 13), instead of
    // from the internals of the `writeFile` function. After that, it
    // will throw the same or a new error so that the program will fail
    // early, instead of continuing with the wrong data.
  }
}

require('fs').writeFile(
  'some_non_existent_directory/test.txt',
  '',
  throwIfError
);

Somebody suggested this solution:

function throwIfError(err, fromwhere) {
  if(err) {
    console.log(`Error came from ${fromwhere}`);
  }
}

require('fs').writeFile(
  'some_non_existent_directory/test.txt',
  '',
  err => throwIfError(err, 'fs.writeFile')
);

But I don't like it because:

  • You have to manually indicate it. This feels just wrong.
  • It will not include the file name/path and line number.

So, what's the solution for this?

ugultopu avatar Dec 18 '20 01:12 ugultopu

How about this:

require('fs').writeFile(
  'some_non_existent_directory/test.txt',
  '',
  err => console.trace()
);

It produces:

❯ node index.js
Trace
    at <file-name>.js:4:18
    at node:fs:1472:7
    at FSReqCallback.oncomplete (node:fs:179:23)

RaisinTen avatar Dec 18 '20 13:12 RaisinTen

That defeats the purpose because now the callback is being defined at the place that it is passed (to a function). The purpose was to define a "general-purpose" callback once, and use it in multiple places.

As far as I can tell, this is impossible. That is, if I'm not wrong, the only way to understand this is to supply the stack trace information in the error. Normally, when you create an error (say, using const err = Error('A message')), the stack information at the time that the error is created is included in the error object (err). However, for some reason, the stack information is not present in the error object that is passed by fs.writeFile. Instead, there is only a copy of the error message with Error: prepended to it.

https://github.com/nodejs/node/blob/b49145f795658c7187a94897d31f665c2fbff471/lib/fs.js#L1499:

openErr: Error: ENOENT: no such file or directory, open 'some_non_existent_directory/test.txt'
  code: "ENOENT"
  errno: -2
  path: "some_non_existent_directory/test.txt"
  syscall: "open"
  message: "ENOENT: no such file or directory, open 'some_non_existent_directory/test.txt'"
  stack: "Error: ENOENT: no such file or directory, open 'some_non_existent_directory/test.txt'"
  __proto__:
    constructor: ƒ Error()
    message: ""
    name: "Error"
    toString: ƒ toString()
    __proto__: Object

Hence, when I print or throw this error in in throwIfError function, I don't get a stack trace simply because there is no stack trace information present in the openErr object that has been passed to the callback.

ugultopu avatar Dec 18 '20 16:12 ugultopu

It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.

github-actions[bot] avatar May 10 '24 01:05 github-actions[bot]

It seems there has been no activity on this issue for a while, and it is being closed. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.

github-actions[bot] avatar Jun 09 '24 01:06 github-actions[bot]