The second message is arguably clearer, but I don't think anyone would be really hindered by the first one, especially given that, unlike in C, application of printf have an explicit type:
# Printf.sprintf "some int: %d another int: %d";;
- : int -> int -> string = <fun>
I think a general tendency in statically typed languages is that we like to write stuff using only the type system, rather than adding code to the compiler. Same for macros: we will rather have them proved correct by the typechecker than make them raise errors (also it is possible, through exceptions).
But maybe this is detrimental to clarity of errors in some cases. I'd be interested to see how Racket handles errors.
By contrast, common lisp and to a lesser extend clojure are also flexible but produce pretty bad error messages (and both have a culture that strongly de-prioritises approachability). This comes at a real productivity cost that doesn't disappear completely even with experience.
In lisp you can write a nice SQL like language or a math DSL without resorting to string parsing. In ocaml you kinda can't because the base syntax isn't that flexible. So I'd expect the problem to be worse and I don't think types are a magic fix. The worst and most voluble compiler error output known to man must be C++ template metaprograming errors.
But maybe this is detrimental to clarity of errors in some cases. I'd be interested to see how Racket handles errors.