AndreasMadsen / trace

Creates super long stack traces
https://trace.js.org
MIT License
194 stars 18 forks source link

Swallowing errors with Axios #56

Closed markwylde closed 2 months ago

markwylde commented 4 years ago

I'm trying to use Axios to make http calls and have the following code.

const axios = require('axios')

async function main () {
  await axios(`https://example.com/xxxxxxxx`)
}

main()

It of course fails with a 404 as expected with absolutely no useful information.

(node:3179) UnhandledPromiseRejectionWarning: Error: Request failed with status code 404
    at createError (/tmp/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/tmp/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/tmp/node_modules/axios/lib/adapters/http.js:236:11)
    at IncomingMessage.emit (events.js:322:22)
    at endReadableNT (_stream_readable.js:1187:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)
(node:3179) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:3179) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

So let's put in trace.

require('trace');
const axios = require('axios')

async function main () {
  await axios(`https://example.com/xxxxxxxx`)
}

main()

This still doesn't give us anything useful.

(node:3184) UnhandledPromiseRejectionWarning: Error: Request failed with status code 404
    at createError (/tmp/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/tmp/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/tmp/node_modules/axios/lib/adapters/http.js:236:11)
    at IncomingMessage.emit (events.js:322:22)
    at endReadableNT (_stream_readable.js:1187:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)
(node:3184) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:3184) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

So I looked into the Axios codebase to see what is going on and discovered they have a createError function. I edited the following...

# node_modules/axios/lib/core/createError.js
var enhanceError = require('./enhanceError');

module.exports = function createError(message, config, code, request, response) {
  var error = new Error(message);
  error.stack += ''; // <------ I INSERTED THIS LINE
  return enhanceError(error, config, code, request, response);
};

Note the only thing I changed was effectively running the setter for stack. error.stack += '';

Again I get nothing. BUT when I install clarify I finally get the information I wanted:

require('trace');
require('clarify');

const axios = require('axios')

async function main () {
  await axios(`https://example.com/xxxxxxxx`)
}

main()
(node:3229) UnhandledPromiseRejectionWarning: Error: Request failed with status code 404
    at createError (/tmp/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/tmp/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/tmp/node_modules/axios/lib/adapters/http.js:236:11)
    at Axios.request (/tmp/node_modules/axios/lib/core/Axios.js:61:23)
    at Axios.request (/tmp/node_modules/axios/lib/core/Axios.js:50:25)
    at wrap (/tmp/node_modules/axios/lib/helpers/bind.js:9:15)
    at main (/tmp/index.js:7:9)
    at Object.<anonymous> (/tmp/index.js:10:1)
(node:3229) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:3229) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I need both clarify and to touch the .stack inside Axios to make this work.

I don't mind having to keep clarify installed, that's all good and I'd be using it anyway. But obviously touching Axios or any other libraries to touch the .stack seems weird.

Am I crazy? Is this a bug and known? Is there anything I can do?

Thanks and amazing projects btw.

markwylde commented 4 years ago

Doing the following in my entry script does seem to fix the issue:

global.Error = class extends Error {
  constructor(message) {
    super(message);
    this.stack += '';
  }
}
AndreasMadsen commented 4 years ago

Sounds like you didn't set the Error.stackTraceLimit.

markwylde commented 4 years ago

Thanks for the response @AndreasMadsen.

I have tried the code below:

require('trace');
require('clarify');

Error.stackTraceLimit = 100000;

const axios = require('axios')

async function main () {
  await axios(`https://example.com/xxxxxxxx`)
}

main()

Which outputs the same "error":

(node:6122) UnhandledPromiseRejectionWarning: Error: Request failed with status code 404
    at createError (/private/tmp/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/private/tmp/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/private/tmp/node_modules/axios/lib/adapters/http.js:236:11)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:6122) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:6122) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.