Notes: Error Logging in React

May 16, 2025

Notes on Error Logging in React

Goal

Need to optimize error logging to help support team diagnose issues faster. Key metric: time-to-root-cause.

Core Error Structure

JavaScript errors are objects with:

  • name: Error type (e.g., "TypeError")
  • message: Human-readable description
  • stack: Call stack (non-standard but universally available)

Example:

const err = new Error("API failed");
console.log(err.stack);
// Error: API failed
//     at fetchData (utils.js:15:3)

Console.log Behavior

  • Outputs multiline string combining name, message and stack
  • Not ideal for transport (formatting can cause truncation)
  • Serialization quirks:
    • JSON.stringify(err){} (useless)
    • Better: JSON.stringify(err, Object.getOwnPropertyNames(err))
      {"name":"Error","message":"API failed","stack":"..."}

Extended Error Patterns

Common library patterns:

  1. Override name (e.g., "HttpError")
  2. Add custom props (e.g., statusCode, url)
  3. Maintain original stack

Example from Axios:

try {
  await axios.get('/data');
} catch (err) {
  console.log(err.isAxiosError); // true
  console.log(err.response.status); // e.g. 404
}

Production Stack Traces

Observation:

  • Even in minified builds, axios errors show clean stack traces
  • Likely using source maps internally
  • Our app should configure source maps for same benefit

Context to Capture

For effective debugging:

  1. User info (sanitized):
    • User ID
    • Current route
  2. Action context:
    • API request/response snippets
    • Redux state slice
  3. Custom error wrapper example:
    class CheckoutError extends Error {
      constructor(message, cartState) {
        super(message);
        this.cartState = cartState;
      }
    }

Sentry Integration

withScope pattern:

Sentry.withScope(scope => {
  scope.setUser({id: user.id});
  scope.setExtra('checkoutState', checkoutStore.snapshot());
  Sentry.captureException(err);
});

Benefits:

  • Attaches context to specific errors
  • Doesn't pollute global scope
  • Breadcrumbs track user journey

Key Insights

  1. Always serialize errors with all properties
  2. Wrap generic errors with domain-specific context
  3. Source maps are crucial for production debugging
  4. Sentry scopes > global tags for error-specific context