It really is. I often have to go and modify some (tail-call-optimised-away) code just to get it to turn up in a stack trace so that I can continue with what I’m debugging.
Just yesterday I had to reason about a stack trace involving tail calls. I worked it out. I wouldn't rather lose TCO so I could get stack traces that I don't have to reason about.
It's no worse than a do-while loop.
Why debug optimized code?
Because that's the code that throws the exceptions after the product has left the lab.