-
-
Notifications
You must be signed in to change notification settings - Fork 926
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error handling in view #1937
Comments
I agree it'd be nice to have it clear the view on own or child error (React changed to do this recently), and to have some sort of error handling function. In the past, it's been suggested to just have Note that what React has is basically a glorified "catch", and they idiomatically prefer updating the state to request a redraw, which basically causes the view to be re-rendered. That specific solution is bad design IMHO - should you really by default be re-entering a method that just threw? |
Also, I'll drop an obligatory note: AJAX errors aren't synchronous, so there's nothing we can do to handle those kinds of errors. |
@isiahmeadows I meant data from an external source may have undefined properties. Not AJAX errors. |
I'm not really sure that if the best solution would be to update 98% of views or not, there may be an argument for easier detection of something going seriously wrong if everything goes seriously wrong. The surprising part of the sample fiddle was IMO that there was no error logged, rethrowing at the end of the redraw cycle would probably be ideal. |
@orbitbot Thought I'd clarify a few things:
|
@isiahmeadows Calling lifecycle methods would be awesome! A lot better than I can do today! |
Regardless of whether a more sophisticated catch equivalent is developed or not, silently handling the error ("The surprising part of the sample fiddle was IMO that there was no error logged") hardly seems desirable behavior. Perhaps 'Expected' behavior should be extended to explicitly include both points -- (1) rest of the app updates and (2) the error logged or otherwise made visible to the calling function? |
@pygy @tivac WDYT about this feature request (and maybe my proposal)? |
Just lost an hour because errors in view methods are currently swallowed by mithril: Line 1046 in bdb04e1
Logging to the console is a must have from my point of view. |
@mpfau Thanks for the report, my bad... Errors should be logged with |
@mpfau I just pushed a temp fix for this for those who use the |
Wouldn't that throw in IE9, or are console messages swallowed? |
@orbitbot yes it would hence my remark. We could wrap the |
Details, but AFAIK you can also just check for the existence of |
@orbitbot I put a |
Differently from some here, I do not want any error catching at all. In my application, I would prefer the entire page to crash if anything goes wrong. In fact, I consider half-working pages to be a very bad and confusing thing for users and for bug squashing in general. PHP practices notwithstanding. Anyway, as much as I love mithril, it is creating a debugging nightmare by swallowing any exceptions thrown in my components (in the constructor or in the view method). Putting something on the console is the very least that mithril must do. This is the most urgent fix that mithtril needs IMO. Someone said using "next" has this problem mitigated. Where can I read about what the consequences of using "next" are? Although this is so urgent, it has lingered here for months. Could someone do something? |
@nandoflorestan could you post a repro? I can't have it swallow errors in either v1.1.6 or the next branch. |
@nandoflorestan Also, could you file a new issue WRT that? This is about allowing optional opt-in graceful handling of errors. (Currently, if any errors are being swallowed within the framework, that's a bug.) |
Hi, folks. I'd like to report a subtler wrinkle to this issue: under v1.1.6 if the first render of a component throws an error, it is caught and logged, but it leaves the vnode in a state where it will throw confusing errors about 'onbeforeupdate' in subsequent renders, with most likely serious impact on app behavior. See https://jsfiddle.net/v2dL1cLw/2/ This does not appear to be an issue in |
Unless I'm mistaken, when a mounted 1.1.6 app contains any component that throws an error from its view on the first render, that app is bricked - every subsequent redraw will stop on an exception from mithril's internals. This isn't necessarily a state that a developer can recover from, as corrupted data could be unexpectedly provided from an external source (server request, localstorage, etc) at runtime. I can't imagine this is the intended behavior. (Note: I was mistaken in my comment above when I said the error was caught and logged. It's not.) As the original reporter noted, "I know I can work around this, and I do", but the workaround is pretty extreme: every component in your app needs to catch and handle errors within its |
@isiahmeadows I think it's possible the labels on this issue aren't correct. The original reporter was only suggesting a feature change (errorView) in passing - this issue is primarily describing a bug. |
I think this issue may actually have the same underlying cause as what @barneycarroll reported in #2067 . While that issue is marked as closed (code complete) no fix has been released yet... |
No, the original reporter was asking for Mithril to not blindly swallow exceptions, but to actually handle them meaningfully, a feature request. var ErrorComp = {
view: function () {
console.log(data.flag)
throw new Error("something went wrong")
}
}
// Let's try to render it
m.render(document.getElementById("app"), [
m('div', 'Some text')
m(ErrorComp),
m('div', 'Some text')
]) <!-- The original element -->
<div id="app">
<button onclick="alert('Hello!')">Click me</button>
</div>
<!-- What's currently rendered, ignoring comments/whitespace -->
<div id="app">
<!-- Element cleared, but `ErrorComp`'s view caused rendering to fail -->
</div>
<!-- What OP wants, ignoring comments/whitespace -->
<div id="app">
<div>Some text</div>
<!-- ErrorComp's view failed to return a vnode tree, so it's ignored -->
<div>Some text</div>
</div> It's distinctly different from #2067, which is about an (admittedly difficult and obscure) bug about |
@isiahmeadows I still think you're mistaken about the original reporter. Later in the conversation, there's discussion of swallowing errors, but that's not what this issue was originally about. Specifically, the reporter says "the error prevents UI update in the entire app" - which isn't reporting that they can't handle the error themselves, but that it kills redraw. It's as a result of digging into the report and the provided fiddle that I observed the bug from #2067 , which seems to be caused by exiting |
I'm realizing in retrospect that the original fiddle would be exiting early from I'm not sure whether that would trigger the same conditions, but I think I was able to reproduce the |
It'd be super helpful if Mithril could provide the required primitives for fault tolerance, though, and that's basically what people here are asking for: built-in fault tolerance for rendering + basic primitives to leverage that in their applications. And yes, mitigating and logging production crashes (so you can properly handle them and maybe even restart the component) are the main selling point of these kinds of hooks. It's what powered the zones proposal (used/pushed by Angular), it's why domains are so popular in Node backend servers, and it's why React added My proposal was strongly inspired by React's, but there are several minor differences like calling |
@barneycarroll I'm concerned with user-facing exceptions, not the developer experience. Your flem is a good example of the code you'd need to have confidence that you're not going to brick on an unexpected error, but it seems strange to expect something like that to be a userland implementation. As soon as anyone (new dev on the team, third party component) manages to use a component with a stock @isiahmeadows I agree that mechanisms for fault tolerance would be excellent, and I think that's what some of the discussion on this issue is about. I'm just trying to scope this issue to safety in production, for 1.1.x (or whatever the current stable release is) - the problem isn't that the error can't be handled by application code, it's that an error thrown in a view leaves mithril's internal vdom state broken and throwing spurious errors on subsequent redraws, as in #2067 . A band-aid fix to 1.1.x would seem to be an acceptable solution to this facet of the issue. I didn't manage to dig down to what was actually breaking in the vdom, so my PR was not even a band-aid, just a hack. I was not able to reproduce this issue in 1.2, so my assumption is that as soon as a new release supersedes 1.1.x as the stable release, this issue is probably dead. |
@pygy, @barneycarroll, and I came up with a plan. Here's the concerns I believe need addressed when it comes to fault tolerance in Mithril, in decreasing priority:
The first two bullets will be the focus of this bug, but the other 4 will be discussed in #2273. Resolving the first 2 will mean this flems should log |
Pardon for the radio silence here! It's been awfully quiet, and I've been spending more time on the job hunt and elsewhere than actually writing code for Mithril. Plus, I've had an uncooperative computer for a while, which certainly hasn't helped things. So here's my current plan. Note that assuming this gets merged (unlikely before v2.1.0), it would be released in one atomic step in a future minor release. I'll likely run a release candidate with this first, so it gets some testing in case I miss something, as it is a complicated thing to implement. Error trackingErrors are tracked and captured in three cases:
Other errors may be tracked and captured (such as some internal errors), but only these are guaranteed captured. Errors are classified by phase. If an error occurs in either Errors are captured along with a stack trace of components. This is used so components can know where an error originated from and optionally send that pretty-printed to wherever. Error handlingA special vnode
In both cases, the stack trace received by each callback is not further used by Mithril after you receive it, so it's safe to mutate and so on. If you omit either attribute, it's simply propagated. This separation is because errors that are caught by The At the top level, you can just do Error propagationErrors propagate from their child to their parent automatically unless the child does has its When errors propagate past the root, they trigger default handlers:
ImpactThis is technically non-breaking, as it codifies currently-undefined behavior.
FutureIn the future, I'd like to also hook up event handlers similarly so errors from them get propagated from their originating component. However, this being a breaking change, that's not going to be in this and will wait until v3 before it'd land. |
@isiahmeadows Pardon me as well for my radio silence! This plan sounds great to me. I'm ambivalent about future plans for propagating errors from event handlers. 😄 |
@michaek The idea is that errors from event handlers still could risk invalid state occurring. And of course, this is just my proposal - it's not necessarily the final product, and I very much do want to encourage discussion on the specifics of it. 🙂 |
It seems like Mithril does not handle errors thrown in the view function.
My personal experience is that if an error is thrown inside the view, the UI does not get properly updated. Not only the component fails to be updated, but the entire app as well.
Context
In this example, an error is thrown inside
ErrorComp.view
. The error prevents UI update in the entire app, hence button label is not updated.Fiddle here.
Steps
Expected
ErrorComp
not to render, but the rest of the application to update (button label to showfalse
).Actual
The UI does not update.
Suggestion
Mithril could catch the error and render an empty string where the component should be (and log the error). Maybe an
errorView
method could be supported (if defined).It is all too easy to get an error in a component. For example if part of a data path is undefined, as loaded from AJAX. I think keeping the rest of the UI up to date would result in a more robust application. One that I as a developer can trust will work in the wild.
I know I can work around this, and I do. But I think Mithril could do better, and be more friendly to devs.
The text was updated successfully, but these errors were encountered: