Lots of answers point to a very traditional approach for general code problems, debugging whether with a formal debugger or a with a manual strategy that mimics debugging.
Another well known way to approach a code problem is to write an automatable testbefore you even look at the code in question. Maybe write two. Maybe three. Design your tests to isolate the aspects that contribute something to the problem function. Then write a few for that particular function, with varying values for the contributions (use some variation in the contribution: known or expected 'good' values, and known or expected 'bad' values. Exercise the function in a manner that you would if it was being used for real, but substitute or fake parts that are extraneous.
Other problems, perhaps with tooling or runtimes, are often configuration issues. Perhaps certain environment variables are needed and normally set, but something about the environment setup changed and those values are no longer defined. Perhaps a single security patch or security policy change did the damage (eg host/port restrictions, permissions, ownership). The important thing is to take note of whether or not that if until now, everything normally worked, and if so, what changed, even if it may on the surface appear unrelated, it still may have indirect but significant consequences.
One time while working on a COBOL project, the C tooling was upgraded. Shouldn't be an issue for me? But it was. A particular version of a library from the C package was necessary for certain aspects of the COBOL runtime process. This dependancy was only one of many of the C package files that were updated, but it was still important, and not part of the 'stated' requirements for our COBOL package. And while the issue was relatively easy to address in our development environment, the same solution wouldn't work on the client/user machines, so we had to change how our software was linked and distributed.
If it worked before, and anything changed, and it doesnt work now, the anything should often be the first culprit.
If something was changed, but the effect wasn't apparent in the outcome, it might be a stale intermediate build file, a stale cache, any other locked file, or stuck process.
If it worked before, and absolutely nothing changed, I often move to looking at hardware. Cables securely and properly plugged, free of significant knicks or abrasion that might result in short-circuiting or interference or worse. Ram test, drive checks, etc. Parts age and fail. Dust and heat are mortal enemies of electronics. Is the machine of concern in a mostly ideal environment for the computer and is proper dust preventing and removal performed.