Worst of all, the method could return normally but leave some object in a compromised state, causing an error at some unrelated point in the code at some undetermined time in the future.
I think this (does it "leave some object in a compromised state") should be the most significant decision factor. Otherwise I don't agree that you should _always_ check params for validity. It's not _always_ worth the extra code (and the complexity/maintenance it comes with) and runtime cost to protect a caller from themselves. (This is a little bit like StringBuilder or DateFormat: these are not safe for multi-threaded use, we don't introduce the overhead of making them so, and if you do use them with multiple threads that's your problem).
Another important decision factor: Does the caller need to know why the failure occurred?