The classic "print-statement-debugging" techniques may work for simpler cases, but quickly get unmanageable. The checklist below is an effective way to find and fix bugs.
"What makes me think there is a problem?"
"How can I reliably reproduce this problem?"
"How can I narrow down to the code that could cause this problem?"
"What information can I gather from this identified code?"
"How can I check my hypotheses about the issue?"
"How can I fix the issue, and confirm that the fix works?"