Depends on the environment I’m using.
First I always try to make a guess. I usually know my code enough to know why it fails. Sometimes, however, it’s not that easy, or I don’t debug my own code.
If I can attach a debugger (like in case of my programs written in C), I just do that immediately. It can show me the stack trace, variable values, and a lot more. If that’s not going to help, nothing will.
If there is no debugger available, I just add some debug log/print statements. That’s much more dirty, especially if reproduction of the bug is time consuming. Still, it’s better than nothing.
And if I can’t find anything, I simply ignore the bug and start working on a different problem. Bugs are careless, and if they see you don’t try to squash them, they will come out in the plain, so whenever you go back squashing them you will have an easy time.