1. Debuggers are in some sense anti-unix. They only work well when they are thoroughly integrated with the rest of your environment. Trying to have some debugger program like gdb and then talking to it from emacs or a terminal or something will be a big pain. Emacs is also anti-unix but seems to have enough mass that it doesn’t matter so much (or maybe the debugger and emacs fighting for importance is problematics)
2. Getting a debugger to work well is hard. Apart from needing information to work out what bit of code is executing (and passing all that information through weird compilation steps or linking), the debugger needs to understand the memory layout of objects and interpret some subset of the language so that people can enter eg watch expressions. This is hard when the compiler and debugger are quite separate and just agree on the format for possible debug information. Lack of integration hurts again
3. Some people are so used to not having a debugger that they don’t know what they’re missing. Debuggers work well for what, windows and websites? I guess Java too? Lots of people end up debugging with prints and that just isn’t so effective. I think I’ve barely used a debugger for more than trivial websites in the last 10 years.
4. The problem of debugging has become harder: there are now more threads in programs and it is more common for languages to have some kind of async mechanism. If you naively debug that, you’ll see crap stacktraces (a few frames sat atop a scheduler) and execution may move randomly between threads in a pool. I feel like most debuggers can’t cope. (I guess website debuggers do understand async better and there are also new inventions like reversible debugging with rr, but the problem with integrating a debugger with a language or an editor remains.)