This is one of the strangest errors I've ever seen.
I'm doing a very simple call to return values from the HttpRuntime cache. The call is:
return HttpContext.Current.Cache[cacheKey];
If it returns null, that's fine. I check if the returned value is null and act accordingly. I've been using this call for a long time.
Recently, for some reason, when cacheKey is set to this exact value:
"Topic_GridSelectAll:5,null,2010-08-31-20-00-00,Published,desc,5,1"
a System.OverflowException is thrown: Negating the minimum value of a twos complement number is invalid.
Nothing about the call, associated code or server has changed. If the cacheKey has slightly different characters, it works perfectly fine. For instance, this cacheKey returns null without throwing any exception:
"Topic_GridSelectAll:5,null,2010-08-31-21-00-00,Published,desc,5,1"
Notice, the only difference between those two strings is the time characters: 2010-08-31-20-00-00 versus 2010-08-31-21-00-00.
Why the hell would that make any difference? And why now after all this time?
The stack trace is:
[OverflowException: Negating the minimum value of a twos complement number is invalid.]
System.Math.AbsHelper(Int32 value) +12753486
System.Web.Caching.CacheMultiple.UpdateCache(CacheKey cacheKey, CacheEntry newEntry, Boolean replace, CacheItemRemovedReason removedReason, Object& valueOld) +142
System.Web.Caching.CacheInternal.DoGet(Boolean isPublic, String key, CacheGetOptions getOptions) +122
MyProject.Helpers.CacheHelper.GetData(String cacheDomain, String cacheKey) in ...
I've tried changing the cache call to use HttpRuntime.Cache instead (ie. HttpRuntime.Cache[cacheKey]
), but that made no difference. I know it's the same underlying cache provider, but I thought maybe the different call would make a difference. No dice.
It looks like on your platform,
GetHashCode()
(in System.String) for that exact string is returning-2147483648
. You could test this (as I did) by putting that string in and simply calling GetHashCode() for it. Every string gets a hash code, and this is one. So what? well....CacheMultiple.UpdateCache
callsGetHashCode()
on your key string, then callsGetCacheSingle()
, which callsMath.Abs
, which eventually callsAbsHelper
. AbsHelper throws an exception if the number is exactly equal to -2147483648! (since the absoulte value would be one more than the maximum value that can be held)So, congratulations, you won the
GetHashCode
lottery - out of 2^32 possible values, you got the right (well, wrong) one. Unfortunately, it seems that the internals of Web.Cache don't handle this at all, so you would have to callGetHashCode
on your string to see if it was equal to -2147483648, and if so alter the string slightly. Or, trap for this exception - and if caught, try again after slightly altering your key (in a predictable manner so that you can recreate it the same way again).Nice bug find - I'd probably go ahead and put a bug on the Connect site if I were you... in my opinion, it shouldn't be the responsibility of the caller to detect and correct edge case problems due to internal implementation decisions.