The overall conclusion is correct, most error messages happen by accident, but a lot the examples look like expected behavior to me. Maybe because Ive been using Clojure for too long, or maybe because its the expected trade-off when using a dynamically typed language. You get more fluidity at the cost of type checks - The way to mitigate this downside is adding checks of your own. Clojure has supported this since way back when using pre/post conditions.
Example:
core> (defn mydiv [n d] {:pre [(pos? d)]} (/ n d))
#'mydiv
core> (mydiv 10 2)
5
core> (mydiv 10 0)
AssertionError Assert failed: (pos? d) core/mydiv
As opposed to the standard core> (/ 10 0)
ArithmeticException Divide by zero
clojure.lang.Numbers.divide (Numbers.java:158)
Chasing down Numbers.java will take time, but with a pre-condition you get the exact name of the function and the test which failed.