Hacker News new | ask | show | jobs
by Geezus_42 64 days ago
As a sysadmin, not developer, I hate Java almost as much as Windows. The error messages Java apps produce are like coded messages that you have to decipher.

I.E. Instead of "<DOMAIN> TLS Handshake failed" it will be something like "ERROR: PKIX failed". So now I have to figure out that PKIX is referring to PKI and it would make too much sense to provide the domain that failed. Instead I have to play the guessing game.

4 comments

Did you mistype Go?

Java has proper error messages with a full stack trace that tells the whole story.

Of course individual developers may lazy out on writing useful error messages, but that's hardly a Java issue.

Meanwhile in Go you can be happy to have any error message at all. And then you can hope it's a unique string you can grep in a codebase. Where you only may find a line of code you could have arrived from many different places.

See my other comments about how stack traces are un-ergonomic for sysadmins. I'm sure they are great for developers.
Btw, Go does have runtime exceptions, they just call them Panics and don't have any nice tooling around it. :)
I hate when tools only produce generic "TLS Handshake failed" instead of saying why exactly it failed, where is the problem.
Sounds like you'd both be happy if the tool produced both.
And Java typically does produce both (see Exception "cause" field). So when an exception stack trace is printed it's actually list of stacktraces, for each "cause". You can skip stacktraces and just concatenate causes' messages (like people often do in Go).

So the full message would be like "Cannot add item X to cart Y: Error connecting to warehouse Z: Error establishing TLS connection to example.com 127.0.1.1: PKIX failed".

Sounds to me that deepsun and I are in agreement that an error message should tell you what the actual error was.

I.E. ERROR: TLS handshake failed: <DOMAIN> certificate chain unverified

People give Go's error handing a lot of flak, but I personally love the errors that come out of a quality codebase.

Just like your example: single line, to the point and loggable. e.g.

  writing foo.zip: performing http request (bar.com): tls: handshake: expired certificate (1970-01-01)
Exceptions with stack traces are so much more work for the reader. The effort of distilling what's going on is pushed to me at "runtime". Whereas in Go, this effort happens at compile time. The programmer curates the relevant context.
What?

What you write makes zero sense, see my comment here: https://news.ycombinator.com/item?id=47750450

And come on, skipping 5 lines and only reading the two relevant entries is not "much work". It's a feature that even when developers eventually lazied out, you can still find the error, meanwhile you are at the mercy of a dev in go (and due to the repeating noisy error handling, many of the issues will fail to be properly handled - auto bubbling up is the correct default, not swallowing)

Different strokes for different folks.

The Go errors that I encounter in quality codebases tend to be very well decorated and contain the info I need. Much better than the wall of text I get from a stack trace 24 levels deep.

This is why stack traces exist. But I agree Java seems to not really have a culture of “make the error message helpful”, but instead preferring “make the error message minimal and factual”.

For what it’s worth, the rise of helpful error messages seems to be a relatively new phenomenon the last few years.

A stack trace that is >10 pages in less is not what I would call minimal.
And that's why you should have multiple appenders. So in code you write "log.error("...", exception)" once, but logging writes it in parallel to:

   1. STDOUT for quick and easy look, short format.
   2. File as JSON for node-local collectors.
   3. Proper logging storage like VictoriaLogs/Traces for distributed logging.
Each appender has its own format, some print only short messages, others full stacktraces for all causes (and with extra context information like trace id, customer id etc). I really think STDOUT-only logging is trying to squeeze different purposes into one unformatted stream. (And Go writing everything to STDERR was a really strange choice).

https://www.baeldung.com/logback#bd-appenders

Cool. Convince your fellow Java developers to do that and I'll quit complaining about the awful errors every Java app produces.
This is the kind of scenario that is served better by Go/C-style error values than exceptions. Error values facilitate and encourage you to log what you were doing at the precise point when an error occurs. Doing the same with exceptions idiomatically often requires an exception hierarchy or copious amounts of separate try/catches.

The difference really becomes apparent when trying to debug a customer's problem at 3am (IME).

This couldn't be further from the truth.

There is no ecosystem I would choose over Java when it comes to observability and it's not even close.

Good luck finding your segfault, oom, race condition or just simply lazy logging culture bug with a C/go codebase at 3am.

I will happily see my proper stack trace, heap dump, or connect directly to prod with a debugger with basically no performance penalty.

Your stack trace tells you where in the code the error occurred, but doesn't tell you what it was doing with what data. For that you need to pass context for the error up the chain of calls, adding to it as you go up. Exceptions are not a great way of doing it as you only have the local context, which isn't a great help when you're catching N levels up.

And if you're not catching N levels up but catching at each level, then you are emulating error values but with try/catch blocks.

That is great for you as a developer. As a sysadmin supporting other people's crap, stack traces and heap dumps are useless beyond forwarding them to the vendor.
So your issue isn't with Java, just with shit error messages and devs clearing the exception stack.
I would believe you, except that it is a problem with every Java app I have supported, and there are people in this very thread defending it.

I do not want a stack trace unless I specifically request it. I am not a Java developer, 10 pages in less showing names of packages I don't even know what they are is not useful. It just muddies the water so that it's much harder to make sense of and spot the relevant line; assuming there is a line that actually states the error. I shouldn't need to know what all those packages are in order to figure out why Confluence crashed again or stopped sending emails.

When you are administrating so many Java applications, you should investigate an hour or ask your favorite AI how to configure the logging library used in your application of interest. They allow you to remove stack traces and lots more.
That would require convincing the entire organization to change SOP and use a non-standard configuration of the vendor software in a high security private cloud.
Then I've never seen anyone write good Java. Either way, same issue.
Tell your developers to start logging the exception, not just a hard-coded error message.
Not my devely. Most of us support stuff written by external vendors, and most of us don't get to choose who that vendor is.