I've noticed that a source of a lot of bugs while I'm programming is stack-trace-decorrelated errors and generally location-decorrelated errors. I'll explain:
When you make a syntax error, the parser catches it and tells you the exact line (and sometimes character number) the error is at, and you can immediately fix it. Here, the location of the detected error is equivalent to the location of the error itself. If you make an error that the runtime checks for (like setting an out of bounds index of an array when the runtime does bounds checking), then an exception is thrown and the stack trace says the line the exception was thrown at, and so you can immediately fix it. The location of the detected error is equivalent to the location of the error itself. You might also see situations like when you set a variable, then a few lines later an exception is thrown, in that case the detected error in the stack trace is correlated (in the informational sense) with the actual error location
But there are certain situations where the real error locations *aren't* correlated with the detected error locations. Like, you incorrectly set an object's property `obj.x` in function `g` called by function `F`, then `g` finishes and `F` then calls function `h`, where an exception is thrown because the error with `obj.x` is detected. The stack trace in this case will show `F` and `h`, but the actual error location in `g` won't be shown on the trace. The detected error location is decorrelated with the actual error location. Note that they're still correlated because they both are in `F`, but they're less correlated than if the detected error is in `g` with the actual error
One way I've found to combat this is to check for the good form of some state immediately after state changes. Like: `changeState(obj); checkIsInGoodForm(obj)`, where `changeState` could potentially produce a stack-trace-decorrelated error. If `changeState` does produce an error, then `checkIsInGoodForm` is likely to catch it. Here, `checkIsInGoodForm` could be anything from a single assertion (`assert(obj.x > 0)`, `assert(i < array.length)`, etc), to expensive, complex functions. This is also one of the advantages of using automatically applied invariants if your language / runtime supports them: they necessarily apply `checkIsInGoodForm` automatically after any corresponding state changes
If anyone has any other strategies, techniques, resources, etc for preventing and detecting stack-trace-decorrelated errors, please tell me!