Error objects in W3C APIs
domenic at domenicdenicola.com
Tue Feb 4 09:49:34 PST 2014
From: es-discuss <es-discuss-bounces at mozilla.org> on behalf of Allen Wirfs-Brock <allen at wirfs-brock.com>
> I've designed exception handling systems before and designed and worked with complex exception hierarchies. My main caveat is that they are somewhat of an attractive nuisance. It's easy to get into designing beautiful classification hierarchies of dozens of different kinds of exceptions, each with their own specific failure information that is captured. In practice, I've found very little actual utility for them.
My (more limited) experience is the same. However, I think the utility that the DOM specs try to capture with their errors is different than that captured by the exception hierarchy that one might think of when looking at them. Let me set the stage:
There seem to be a few possible properties of an exception that could be varied depending on the situation:
- The type. Typically this is very broad in ES, and in the DOM even more so (everything is `DOMException`). In ES this is the same as the `.name` property, but not in the DOM.
- The category. ES has no such concept, but DOM specs use the `.name` property for this, with a variety of generic categories like "InvalidStateException," "NetworkError," etc. 
- The human-readable message. This is never specified, from what I can see.
- The proximate cause. By this I mean the exact situation or line of the relevant spec that caused the error to be thrown. Every such cause should be distinguishable, even if they belong to the same category. Usually there will be a one-to-one correspondence between human-readable messages (or message format strings, with appropriate placeholders) and machine-readable proximate causes. I've seen this rarely, but some parts of Node.js use error codes for this.
I have not seen much attention paid to the "proximate cause" idea in the wild. But I think it is perhaps the most important. Allen's point about hierarchies being largely useless resonates with me on the type and category level. That is, even the DOM's more fine-grained exception categorization is not that useful if I am trying to recover from a specific scenario. Whereas, the ability to specify specific situations to recover from would be much more fruitful.
For a great example of these levels, see [recent discussions on the streams repo]. We have two situations: writing to a closing stream, and writing to a closed stream. On an ES level, these would end up as both `TypeError`s, as [discussed], with no further distinguishing information besides implementation-defined `message`. Working on a DOM level would be no different, I think: both would likely become `DOMException`s with `name` of `"InvalidStateError"`. What we really want is a machine-readable (and thus rigorously specifiable) "proximate cause" field that consumers could use to distinguish which situation they got themselves into, especially e.g. in logs. As-is, we just [folded them both into `TypeError`] with no detail on the cause, hoping implementations would be helpful about this.
All this said, I think the DOM's categorization, and my proximate cause idea, are both trying to allow you to distinguish failure modes. You could envision, especially [with better syntax support], letting most errors bubble, but catching and handling `NetworkError`s with a retry. It would be even better, I claim, to be able to handle "network error from no network" separately from "network error due to server misbehavior", thus the proximate cause idea. This divide, between categorization and proximate cause, is part of why I think the DOM's exception categories evoke semi-useless exception hierarchies, even if they are aiming at a useful goal.
As you can see, I Have Opinions on this. I also know a number of community members who do as well. I'd love to discuss this further and perhaps pick up on that strawman idea you are suggesting, Allen.
More information about the es-discuss