6 ms·
Pike is totally wrong here, and trying to explain his way out of a poorly thought out error type. > In contrast, a stack trace-like error is worse in both resp
by anameaname 9y ago
Pike is totally wrong here, and trying to explain his way out of a poorly thought out error type.
> In contrast, a stack trace-like error is worse in both respects. The user does not have the context to understand the stack trace, and an implementer shown a stack trace is denied the information that could be presented if the server-side error was passed to the client.
Absolutely not. The stack is useful to the implementer, the error message is useful to the user. You include both. Want it on both sides? Send it to both sides. Turning a stack trace into a string and propagating it around is not so expensive, and incredibly useful.
Here's a common error I see in Go: "os: file does not exist". What file doesn't exist? Upspin fixes that oversight, but the very next thing to ask is who wants that file? Without the stack trace you'll never know why /tmp/dfgsdfg was needed and who couldn't find it.
> For those cases where stack traces would be helpful, we allow the errors package to be built with the "debug" tag
Ever have those times where a binary is acting wonky, and once in a blue moon raises an unusual error? You can't just rebuild the binary and deploy it to 10,000 machines to debug it. It needs to be on all the time.
It is unbelievable the mental hoops the Go implementers jump through to explain how their anemic error type is actually better.
- pjmlp 9y agoYou see this pattern in every feature that isn't quite right in Go.
- ynezz 9y agoI don't agree, but if you think so, you can try making go2 better via https://github.com/golang/go/wiki/ExperienceReports https://github.com/golang/go/wiki/ExperienceReports
- pjmlp 9y agoI don't believe Go 2.0 will ever happen. So far that page looks like when our government puts out "work commission" for any ongoing problem people complain about. Go mailing lists have almost zero meaningful activity regarding Go 2.0.
- ynezz 9y agoSource: https://blog.golang.org/toward-go2 https://blog.golang.org/toward-go2 > I don't believe Go 2.0 will ever happen. "Once all the backwards-compatible work is done, say in Go 1.20, then we can make the backwards-incompatible changes in Go 2.0. If there turn out to be no backwards-incompatible changes, maybe we just declare that Go 1.20 is Go 2.0." So yeah, Go 2.0 might not even happen. > So far that page looks like when our government puts out "work commission" for any ongoing problem people complain about. I would love if my government would take some inspiration from such projects, namely from this: "We did what we always do when there's a problem without a clear solution: we waited."
- pjmlp 9y agoIf Cloudflare hadn't exploded as it did, they would not have done any fix. So lets see what actually happens to those issues being reported.
- oblio 9y agoOftentimes the stacktrace is useful even to the user. "Foo calling Bar, which fails. Let's check if Foo is configured correctly". Even the abominations that are Spring stacktraces are useful. I think every language that can include them should include them.
- natefinch 9y agohell no. Rule #1 - users should never see stack traces. Every time some python tool fails and dumps a stack trace, I want to throw my computer across the room. As as user, I never want to see a stack trace. I have zero interest in debugging some random tool. Show me a decent error message with tips on how to get more info. If you want a stack trace that I can give in an error report, put it in a log file somewhere.
- aleksi 9y ago> Here's a common error I see in Go: "os: file does not exist". What file doesn't exist? That error contains file name: https://play.golang.org/p/Ea8FKF82c9 https://play.golang.org/p/Ea8FKF82c9 Package documentation is clear on that: https://golang.org/pkg/os/ https://golang.org/pkg/os/
- heavenlyhash 9y agoI've come to disagree with the notion of stacks being attached to every error. And I say that having previously authored a library for attaching stacks to every error in golang, and having used it for several months in several projects. It's very useful for errors to say something about where they're from. It's possible to do that in more ways than simply having a line number -- I think we've all become a little to quick to be reliant on line numbers as the best, or even only way to tell that story; it just ain't so. Line numbers are great when you're in a development cycle on your own personal laptop, and the source checkout and one binary you're running are in lockstep. Line numbers become completely insufficient when you're debugging a large system, particularly if it has more than one version of a particular process. Quick, what's "Line 169" mean when it shows up in your logging bucket during a rolling blue/green deploy of your code to a >100 node cluster? Stack traces are just a slice of line numbers. They're not magical, and since it's not a given that line numbers provide all context necessary to trace something, it follows that stack traces don't necessarily provide all context necessary to trace something either.
- sciurus 9y agoStack traces not providing enough context necessary to trace something is an argument for attaching, more information to errors, not less. Checking entries in my https://sentry.io https://sentry.io installation, for example, I see the exception, the stack trace, the server the error occurred on, the release it was running, the URL being accessed, the values of local variables, etc. Having all this is invaluable for understanding what went wrong.
- ereyes01 9y agoI agree, there's too much uncertainty with line numbers, especially in a changing codebase. A system I used to work on (in C) had the build system generate unique error codes for every unique error point. The codes were 64 bits and consisted of an eye-catcher prefix for easy identification in a hex dump (think it was 0xEEE7), 24 bits identifying the file, and the rest was the error code. Every build generated a map file for you to look up error codes quickly. To generate one of these errors, you called a macro with ugly magic code that generated the unique part of the code, and returned that, logged it in the trace, or whatever. The unique codes served us quite well in precisely identifying where they came from. It would be nice if Go and other languages somehow baked that in for us so you would have a user-friendly error message accompanied with the unique code for developers (which users can just easily ignore).
- xiaq 9y agoGo's rejection of exceptions comes from the philosophical ground that errors should be expected no matter how unlikely they are, and the programmer must make a conscious effort to think about how to handle errors - either by attempting to recover from it (probably with some logging) or passing it to the caller (after annotating and possibly reclassifying the error). Pike argues that different applications require different strategies, and there is no single solution that fits all. No strategy is biased by the language; the choice must be made consciously. Hence no auto propagation of exceptions. Exceptions optimize for the use case of passing it to the caller because that is indeed more common, especially when writing libraries. However, it makes recovering unnecessarily verbose. In the worst case, you may need to nest the call to every exception-throwing function in a try block. Exceptions also carry the danger of spoiling the developer: it encourages developers to think less about errors because they are "exceptions". When errors do happen, the exception being thrown often carries little information about what is really wrong. This problem is mitigated by stack traces, but stack traces do not always have the entire context. If an AccessDeniedException is thrown during a multi-step operation, do we know which user is denied access and which step denies access? A carefully designed library will populate the exception with user information when throwing it, and likely catch and rethrow it to add more information. Does this sound familiar? This is exactly what Pike is advocating in this article. It requires you to think about the execution flow of your program not in terms of function calls, but in terms of more high-level operation steps that the user can also understand to some extent. At the end of the day, even in a language with exceptions, error handling code can still benefit from the approach Pike advocates. If executed well, it makes the stack trace unnecessary, because the "operation traces" should now contain enough information. However, this approach requires a lot of discipline, and the programmer must have a clear picture of all logical operations involved. Unfortunately that is not always possible; programs can easily become too large for one person to completely grasp how it operates in a limited amount of time. To conclude, in the perfect world where programmers always have a clear understanding of all the operation steps involved in a program, Pike's approach is flawless. But in the world we live in where no one ever knows entirely what is going on, automatic stack traces are (still) a sensible fallback. Yet, I take this as a protest against the status quo rather than an oversight: programs should not grow too large for a programmer to grok, and programmers should strive continuously to simplify and understand the programs they maintain.