I would like add my two cents on this topic from software engineering viewpoint.
Before comment on the proposal, I want to state some opinionated principles about error handling. 1. Each component should only catch an exception if and only if the component is responisble to handle the exception. 2. If a component encounter an exception that it is not responsible to handle, the component should propagate up the exception **completely**. Complete means no information lost. These principles applies to multi-language multi-serivce system. For example, in a micro-services environment, a service A written in Nim make an HTTP call to service B written in Java, and service B encounter an exception that it is not responsible to, then service B should return a json response (or whatever format) that contain all necessary info (e.g. error code, error message...) that service A can reconstruct the error completely in Nim. And if serivce A also not responsible to that exception, this process will continue. Go back to the proposal, some comments: 1. The proposal say that "... ErrorCode that covers everybody's use case..." IMO, this is unrealistic. For example, a money transaction `Transaction(sender:AccountId, receiver:AccountId, amount:Currency)` and a procedure `process(t: Transaction)` that process the transaction. The process can fail if the sender do not have enough balance; or if the account of sender/receiver is freezed; or if the sender has already exceed daily transaction limit; or etc. From what I see in the proposed ErrorCode list, generic `Failure` is best for the above three. It is not `PermissionDenied` nor `BadOperation`. In my experience, the unhappy paths are increasing over time, and they must be distinguishable. A generic fixed set of status codes is not practical. HTTP status code is long-known to be ambiguous. HTTP status code is more for observability for third-party tools, rather than error handling within a system. 2. It seems to me the proposal try to avoid "error translation". My understanding of error translation is that a component catch the error X and then re-wrap the error as Y. My point of view (as following the principle above) is that if that translation is part of the responsibility of the component, then go ahead; if not, then no translation should be conducted and the error should be propagated up completely. This depends on application logics, and 'translation of error' should not be considered as evil. 3. IMO, current Nim's error hierarchy is working fine. Co-existing two mechanisms/style of error handling will reduced readability and style consistence. 4. IMO, the cost of throwing exception is neglectable. Any single IO operation takes way longer than exception propagation. And the extra information associated with error are not to be dropped (as proposed to put into thread local storage).