It's tough to make a client use your API correctly. It's especially tough to get clients to not do things that appear to work 90% of the time, but aren't correct and break down in that remaining 10%.  It's even harder for things that work 100% of the time in the current version but may break in the future.

You can try to add checks to your API to force them to do it right, but sometimes you just can't enforce it.  This is along the line of complaints I had here.

The example I'm thinking of involves Thread IDs. So ICorDebugThread gives you the Thread Id  (via GetId). But how does that scale with fibers / logical threads?  So we tried to be clever and say that GetId could change (future-proofing in case a managed thread got rescheduled on different OS threads) as a warning in preparation for fibers.  But since we never implemented fibers, our warning was benign. And so debugger authors may naturally take the dependency on GetId that it's unique for the lifetime of the managed Thread (for example, using it as a hash index or a unique ID to the user).  And things work fine for them. Now along comes fibers and BOOM!! GetId starts changing and the debugger breaks.

Then we get to play the blame game. We can blame the debugger author for not reading the fine print. But end-users will notice that the debugger stayed the same and only the CLR was changed, and so they'll blame the CLR.

Moral of the story: Benign warnings are not future-proofing