rollbar / rollbar.js

Error tracking and logging from Javascript to Rollbar
https://docs.rollbar.com/docs/javascript
MIT License
566 stars 212 forks source link

TypeError when console.log a dynamic Imports #1127

Open francois06 opened 7 months ago

francois06 commented 7 months ago

In a React project using ViteJS, console.logging the result of a dynamic import triggers an error in Rollbar.

Example code to replicate the issue:

App.jsx

import Rollbar from 'rollbar';

new Rollbar({
    accessToken: 'xxx',
    captureUncaught: true,
    captureUnhandledRejections: true,
});

const x = await import('./module');
console.log(x); // raise error

const App = () => (
    <>
        <h1>Hello World</h1>       
    </>
);

export default App

module.js export const x = 1;

The error raised is ;

Uncaught TypeError: Cannot convert object to primitive value
    at Array.join (<anonymous>)
    at Object.formatArgsAsString (utility.js:676:17)
    at e2.<computed> [as log] (telemetry.js:520:23)

Based on my understanding the problem stems from the formatArgsAsString and typeName functions.

The function typeName(x) returns 'module'. Due to this, within formatArgsAsString, the code fails to satisfy any condition in the switch statement.

The final line of formatArgsAsString is return result.join(' ');.

This results in an error because the join method attempts to call toString, which does not exist in this context. Consequently, JavaScript attempts to convert the object to a string and fails, leading to the error message: "Cannot convert object to primitive value."

(in module.js, if we add export const toString = () => 'hello'; the error is not raised.)

Possible correction could be :

function formatArgsAsString(args) {
  var i, len, arg;
  var result = [];
  for (i = 0, len = args.length; i < len; ++i) {
    arg = args[i];
    var x = typeName(arg);
    switch (x) {
      case 'object':
        arg = stringify(arg);
        arg = arg.error || arg.value;
        if (arg.length > 500) {
          arg = arg.substr(0, 497) + '...';
        }
        break;
      case 'null':
        arg = 'null';
        break;
      case 'undefined':
        arg = 'undefined';
        break;
      case 'symbol':
        arg = arg.toString();
        break;
      case 'module':
        if (arg.toString) {
          arg = arg.toString();
        } else {
          arg = JSON.stringify(arg);
        }
        break;

      default:
        arg = JSON.stringify(arg) || String(arg);
    }
    result.push(arg);
  }
  return result.join(' ');
}

or more generic adding a default :

 default:
        arg = JSON.stringify(arg) || String(arg);