Exceptions should be the exception

A hero adventurer completes challenge after challenge on his way to save the princess from the hands of evil. Suddenly, he accesses the first item of his empty inventory. He is now the protagonist of a tragic tale of a design mistake which is second only to the null reference.

In programming, we typically do something that at some point can fail. Say you're writing a program that takes in its second command line argument and writes it to a file named "output.txt".

So the steps would be:

So you spin up your favorite not even close as good as vim text editor and complete your program.

But what if the user forgets to provide input?
What if you don't have write permissions in your current directory?
What if the file already exists?

Errors are a natural part of our programs. So, why do we treat them as something special that needs try { } catch (Exception imGonnaIgnoreAnyways) { }. Why does, in very many popular languages like Python, Java and C#, File.read("mydiary.txt") return a string and not something like a Either<String,FileReadError>.

The biggest problem with exceptions is not try { } catch { }. It's that often, you don't know which exceptions a method may throw. It's like playing a guessing game and I repeatedly in my career found myself doing something like a "defensive try { } catch { }" when I just didn't want a random exception to crash my program. I've also had many stressful nights where in a long running Java deployment there was some exception thrown for a trivial reason, which killed the entire deployment and upset many users.

Thanks for reading. If you're making a language, please make errors and failures first class citizens of your type system. It doesn't always have to be implemented in a monadic way such as in Haskell or Rust. Even something simple like Go's if err != nil is already infinetly better, because the method communicates that it can fail.