react: Can an error boundary prevent React's error logging?
I noticed this unconditional console.error which I’d like to prevent to keep the console clean from errors that are already “caught” in an error boundary.
Maybe a condition on capturedError.errorBoundaryFound could prevent this logging?
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 59
- Comments: 37 (2 by maintainers)
@gaearon
consider the following production issue we are facing: We are using a third party logging service, that logs all
console.errorcalls automagically- which is debatably awesome and at the same time a given fact.Naturally, we have our own ErrorBoundary implementation: We want to slap on extra information special to the boundary instance- So our error boundary component receives this information as props / context, And logs the error along this information using the third party’s sdk when an error occurs.
As a result of this implementation, when a component fails, we have two separate errors logged in our monitoring pipeline: One which react logs, with barely any info, which comes from
console.errorAnd one with everything we need to know, which we explicitly logged via the third party library.Since this redundancy is confusing and not acceptable We are now facing quite a dilemma:
If we don’t explicitly log, we lose error specific info. We also rely on react to do the logging for us, which is a bad idea in the long run.
if we explicitly log - we get two separate events in our monitoring pipeline, which is confusing and noisy, since our monitoring pipeline is automated and triggers a whole lot of internal processes.
I bet that we both believe
console.errorto be a side effect. As an app developer, wouldn’t you agree with me that such a side effect should not be invoked by a UI library without the possibility to opt out?It’s great that I can isolate failures to granular regions in the application- anything other than that, should not be decided for me as a developer. I wouldn’t want to see anything in the console which I did not put there. Especially if it renders the entire stack of my component tree structure, uglified or not.
On the other hand, I do understand where you’re coming from by saying you don’t want it to be easy to swallow errors, so how about this as middle ground: You could move the invocation of
console.errortocomponentDidCatch, Which would be the default implementation unless overriden.if you think of it, this is the correct thing to do, since
componentDidCatchis meant for exactly this. To quote the docs:you say
console.errorand I saythirdPartyLibrary.logError.The means of logging should be up to app developers, especially if they went through the trouble of setting up Error Boundaries.
Since Error Boundaries are basically logging components with some conditional rendering, and since I bet our logging provider is not the only one which logs
console.errorcalls, wouldn’t you say this issue should be solved in a more extensible manner?As for buggy error boundaries, IMHO, you should not care about them. It’s just another failed component, so let it fail until it either crashes the entire tree or another boundary catches it. Since react is solely a UI rendering library, why should it decide what happens when rendering fails?
Don’t close. We can’t seriously unconditionally log this anymore.
Error swallowing should be opt-in. I’d like to swallow certain errors and not others:
I’d support this feature as it would be nice to de-clutter our test output.
@gaearon Would also like to see this fixed. I think ErrorBoundary should have same semantics as exception handling, once an exception has been caught, it’s caught.
If you want to log your exceptions, you should log them in the
catch(), having a helper that logs the error exactly like it’s currently logged might be useful. I guess this would be a breaking change, but IMO it’s worth to have the same semantics as normal exception handling. If breaking change is too big of a problem, then having a.preventDefault()/.preventLogging()works too.If the exception handler (ErrorBoundary) itself causes an exception, that’s a different case, and should cause an exception to bubble up (which presumably could be caught by a higher level handler/ErrorBoundary).
For me there’s two main reasons:
Error stacks are ludicrous when testing error boundaries 😬 yikes.
This is a huge pain and makes the console unreadable in dev mode as well as distracting/scary in prod mode. Some of our errors are “normal” / “handled” for some users or configurations. For instance, if a component doesn’t have the rights to do something, an ErrorBoundary will catch that and show a nice UI. We also use Suspense and the two tie well together.
What I ended up doing to workaround this limitation:
InvariantError extends Error) my custom Errorserrorlistener on window andevent.preventDefault()ifevent.erroris an instance of my custom error. This is for dev builds. This is thanks to this amazing code: https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberErrorLogger.js#L93It really shouldn’t be this complicated and undocumented.
The errors are also unconditionally logged during tests where I expect components to throw and catch the errors myself with error boundaries. This is frustrating and pollutes test output.
@EyalPerry hit the nail on the head. Is there anything more to say? Shall we patch
console.error?I suppose this is still not fixed in React 18 alpha. We still have hopes for stable 18 release.
I’d like this to be fixed as well. The solution @EyalPerry suggested would be perfect.
This is resulting in double errors in our logging system (ErrorBoundary logs it but we also capture console.error) – extremely frustrating.
For now we’d rather not allow it because it makes it too easy to swallow errors (such as if the error boundary itself is buggy).
bump
bump
@anilanar I completely agree with you, I think we should really have the possibility to suppress the logging of some errors which have been handled in error boundaries.
I think that we should have the power and responsibility to decide what to log and what not to log, especially in production.
In my case, if my app has been deployed in production and an error boundary catches an error, I wouldn’t want to log the error to the console leading to information disclosure for some “more smart” users who open the browser’s console to see what went wrong, or at least, I would want to be able to decide whether to log a certain error captured by an error boundary or not.
Also, I think that, when using
create-react-app, it would be great to have the ability to suppress the error overlay for some errors caught by the error boundary (not all, but some), but that’s another story…Right, I see reasoning in that, preventing error logging should require more than just the existance of a boundary.
Browsers allow to suppress logging uncaught errors to the console via
event.preventDefault()in aerrorevent handler onwindow. Maybe a something similar could be done from a error boundary too, likeerror.preventDefault().bump
I’m exploring a pattern in which I throw specific errors when running into unexpected scenarios (i.e. missing or invalid parameters, invalid routes, …) with the intention of moving all of this UI state logic to error boundaries instead rather than repeating it in every page/view. It makes things a lot cleaner, but the unfortunate side-effect is indeed that all of these errors now show up as uncaught errors in the console. Would really love a way to be able to bail out of logging expected errors.
I do understand that intentionally throwing errors does not mean that they are also caught, if you for example forget to handle them in an error boundary, or simply forget to wrap your tree with an error boundary component. Not really sure what the best way around this would be.
My team ran into this issue as well. Would really like a fix.
bump
Yeah, being able to control this logging behavior would be awesome. We are using an extensive logging system and it would be nice to be able to combine the error and the component stack into a single log message this way. While just hiding the second component stack error message is not difficult, detecting the previous “uncaught” window error is the major issue as there’s no ways to identify that it originated from within react.
bump. so many logs i want gone