The error messages are arguably worse with concepts than without them but it's really just a trade-off. Without concepts you got long "stack-traces" of raw syntax errors that could dig deep into nested functions. With concepts you get long stack-traces of concept failures where concept A fails because concept B fails because concept C isn't satisfied and then you need to dig through this chain of concepts to figure out what's actually needed.
Traits in more principled languages like Haskell/Rust don't have this issue whatsoever because traits are semantic requirements in those languages while concepts in C++ just perform a "will it compile" kind of check.
The primary benefit of concepts in C++ is overload resolution, they allow you to write multiple functions with the same name, and same number of parameters, but where the types of the parameters are required to satisfy certain properties.
For example:
void serialize(std::ranges::contiguous_range auto&& range) {
// Serialize the underlying memory directly
}
void serialize(std::ranges::range auto&& range) {
// Serialize elements individually
}
The compiler selects the first overload for contiguous ranges such as std::vector and the second for non-contiguous ranges such as std::list.