5/21/2025 at 11:04:54 AM
The article pretty much says this as well, but a concise way I saw Andrew Kelley put it recently in the context of Zig (but it seems to apply well for any language that has errors-as-values + panics) is: "Assertions for programmer mistakes; errors for user mistakes."[0]One interesting difference between Zig and other languages with similar error stories (Rust, Go) is that panicking can be handled but not recovered. Panicking is always fatal in Zig. The nice thing about this is that you cannot use panics for exception-style control flow, which removes any temptation to use them for user errors.
[0] https://ziggit.dev/t/i-wrote-a-simple-sudoku-solver/9924/12?...
by Zambyte
5/21/2025 at 1:24:59 PM
From my experience, Zig is the worst at error handling.Not that the language itself make it hard, on the contrary, but the standard library itself is littered with opinionated error handling that straight up panic with no recovery at every corner.
For instance, it was decided that the kernel returning EINVAL for any syscall is worth panicking, even though there are a lot of cases where that is recoverable. The answer from Andrew? It's the kernel's fault. Very helpful.
Quotes are cute, but their actual implementation matters more.
by Galanwe
5/22/2025 at 2:35:19 AM
Quotes are cute, and I prefer them over uncited negative claims. Can you link somewhere he actually said that? Because from a quick search I find him saying:> It should be handled on a case-by-case basis. For some syscalls, EINVAL should be unreachable because it can only mean something like an invalid pointer address being passed to the kernel, or invalid flags.
> However, as you pointed out, some kernel APIs unfortunately have decided to dual-purpose this error code to mean other things, in which case we must to handle the ambiguity by mapping it to an error code. We had to make this change with EBADF recently for some syscalls, for example.
> I do want to keep the error sets clean, however, so I am opposed to a blanket modification of all EINVAL code sites without cause.
Source: https://github.com/ziglang/zig/issues/6925#issuecomment-7214...
by Zambyte
5/22/2025 at 2:38:18 AM
> We discussed this in the meeting today and decided that we'll start by changing all => unreachable to => return error.Unexpected in std.posix and std.os.https://github.com/ziglang/zig/issues/6389#issuecomment-2895...
by Zambyte
5/21/2025 at 1:52:04 PM
My problem with panics is that if it is a library (e.g. standard library), then I cannot handle the error the way I want. Let us say that you have a library that parses something. As the user of that library, you want to be able to handle these errors gracefully, you do not want the library to just panic at those parse errors. Sadly I have seen libraries do this.by johnisgood
5/21/2025 at 11:23:53 AM
> which removes any temptation to use them for user errors.It doesn't look to be too much of a temptation to use panics as regular errors in Rust though, so I don't think it gains you much.
And it makes it more complicated when you want to catch panics for legitimate reasons (like when you want to show an error box to the user, instead of silently crashing, or when you want to send the crash log for later analysis). It's still possible, by using a separate process, but it's unnecessary friction in order to prevent a sin that doesn't happen in practice.
by littlestymaar
5/21/2025 at 11:46:20 AM
> It doesn't look to be too much of a temptation to use panics as regular errors in Rust thoughMaybe not, but it was enough for the author to dedicate at least one whole section of the article to reasoning about this.
> like when you want to show an error box to the user, instead of silently crashing, or when you want to send the crash log for later analysis
As I mentioned, panics can be handled but not recovered. You can use the panic handler to do these things just fine. Just not recover.
by Zambyte
5/21/2025 at 4:52:41 PM
> As I mentioned, panics can be handled but not recovered. You can use the panic handler to do these things just fine. Just not recover.What does this difference mean? If you can run arbitrary function in your panic handler, what prevents someone from continuing the program?
by littlestymaar
5/22/2025 at 10:20:10 AM
The stack is fully unwound before running the panic function, including the main stack frame. This will run all deferred deallocation statements, and pretty much leave you with nothing to do but exit. You could try to launch the program again automatically, but there is little reason to do that most likely. The user will still see the application terminate and launch again.by Zambyte
5/21/2025 at 12:13:45 PM
I've never heard of anyone using panic for exception-style recovery. That's anathema to the whole idea of Result<T,V>. But I suppose if it's possible, it will be normal for someone.by jvanderbot
5/21/2025 at 12:58:17 PM
I'm not as familiar with the Rust ecosystem, but I know it is used all the time in Go. For example, the standard http server library wraps user provided endpoint handler functions with panic handlers.by Zambyte
5/21/2025 at 1:23:39 PM
I suppose it's a matter of perspective but I don't see returning a 500 as "Recovering from the error". The user's request has still failed. It just hasn't taken down the server. IMO this is still fine.by dhruvrajvanshi
5/22/2025 at 2:22:42 AM
It is quite literally using the "recover" function in go, so I think it's accurate to call it "recovering".> this is fine
I didn't mention the merit, just that it is exception style control flow.
by Zambyte
5/22/2025 at 10:13:02 AM
Reading my top level comment again, I realized I did refer to the Zig way as "nice" relative to the exception style control flow.by Zambyte
5/21/2025 at 1:19:18 PM
Is that used for application-level errors though? Rust web servers do that too, but it is used a fallback to avoid bringing down the whole server due to an unexpected crash. It is not a mechanism you would use intentionally.by nicoburns
5/22/2025 at 2:23:49 AM
Probably not. I have never used panic / recover in application code at least.by Zambyte
5/21/2025 at 4:39:50 PM
encoding/json uses uses exception handlers for control flow.by 9rx
5/21/2025 at 11:31:36 AM
> Assertions for programmer mistakes; errors for user mistakesThat's been the general mantra for at least a decade or two. And I think it's right.
by 90s_dev
5/21/2025 at 10:40:21 PM
> panicking can be handled but not recovered. Panicking is always fatal in Zig.What does it mean to "handle" but not "recover" a panic?
by hamandcheese
5/22/2025 at 2:20:06 AM
Dumping the log somewhere, telling the user that the program is exiting, things like that.by Zambyte