Stackexchange.redis: [.Net Core] NullReferenceException thrown from StringIncrementAsync(...) when Redis is offline.

Created on 14 Sep 2016  ·  4Comments  ·  Source: StackExchange/StackExchange.Redis

When calling an Async method like this, no Exception should be thrown until the Task is awaited. Kicking off the Task itself should never result in an Exception. In this particular case, if Redis is offline, StringIncrementAsync(...) and likely all of the other *Async(...) methods throw a NullReferenceException from the guts of the library.

System.NullReferenceException occurred
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=StackExchange.Redis
  StackTrace:
       at StackExchange.Redis.ServerEndPoint.get_LastException()
       at StackExchange.Redis.ExceptionFactory.GetServerSnapshotInnerExceptions(ServerEndPoint[] serverSnapshot)
       at StackExchange.Redis.ExceptionFactory.NoConnectionAvailable(Boolean includeDetail, RedisCommand command, Message message, ServerEndPoint server, ServerEndPoint[] serverSnapshot)
       at StackExchange.Redis.ConnectionMultiplexer.ExecuteAsyncImpl[T](Message message, ResultProcessor`1 processor, Object state, ServerEndPoint server)
       at StackExchange.Redis.RedisBase.ExecuteAsync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
       at ... .MoveNext() in ... .cs:line ...
  InnerException: null

Here's what consumption of the library looks like, that generated this Exception (stitching together the bit inside the DI setup with the actual call):

            IDatabase _conn = ConnectionMultiplexer.Connect(...).GetDatabase();
            Task<long> incrementTask = _conn.StringIncrementAsync(... , flags: CommandFlags.DemandMaster);

Here's my work-around:

            Task<long> incrementTask;
            try
            {
                incrementTask = _conn.StringIncrementAsync(... , flags: CommandFlags.DemandMaster);
            }
            catch (NullReferenceException e)
            {
                //An async method like this should not be throwing an Exception (if anything, the Exception should be thrown within the Task), 
                //but there seems to be a bug in the Redis framework where a NullReferenceException is thrown here if Redis is offline, from deep in the guts of their lib.
                //Treat this the same as we would for a RedisConnectionException thrown from inside the Task.
                _logger.LogError(...);
                ...
            }

All 4 comments

Can confirm this on .net 4.6.

Will investigate, thanks.

On 13 Sep 2016 11:33 p.m., "Ken Mason" [email protected] wrote:

When calling an Async method like this, no Exception should be thrown
until the Task is awaited. Kicking off the Task itself should never
result in an Exception. In this particular case, if Redis is offline,
StringIncrementAsync(...) and likely all of the other *Async(...) methods
throw a NullReferenceException from the guts of the library.

System.NullReferenceException occurred
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=StackExchange.Redis
StackTrace:
at StackExchange.Redis.ServerEndPoint.get_LastException()
at StackExchange.Redis.ExceptionFactory.GetServerSnapshotInnerExceptions(ServerEndPoint[] serverSnapshot)
at StackExchange.Redis.ExceptionFactory.NoConnectionAvailable(Boolean includeDetail, RedisCommand command, Message message, ServerEndPoint server, ServerEndPoint[] serverSnapshot)
at StackExchange.Redis.ConnectionMultiplexer.ExecuteAsyncImplT
at ... .MoveNext() in ... .cs:line ...
InnerException: null

Here's what consumption of the library looks like, that generated this
Exception (stitching together the bit inside the DI setup with the actual
call):

        IDatabase _conn = ConnectionMultiplexer.Connect(...).GetDatabase();
        Task<long> incrementTask = _conn.StringIncrementAsync(... , flags: CommandFlags.DemandMaster);

Here's my work-around:

        Task<long> incrementTask;
        try
        {
            incrementTask = _conn.StringIncrementAsync(... , flags: CommandFlags.DemandMaster);
        }
        catch (NullReferenceException e)
        {
            //An async method like this should not be throwing an Exception (if anything, the Exception should be thrown within the Task),
            //but there seems to be a bug in the Redis framework where a NullReferenceException is thrown here if Redis is offline, from deep in the guts of their lib.
            //Treat this the same as we would for a RedisConnectionException thrown from inside the Task.
            _logger.LogError(...);
            ...
        }


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/StackExchange/StackExchange.Redis/issues/483, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABDsMOsMaRIzUmraiddXWS6AJlneDnxks5qpyTOgaJpZM4J8N64
.

Actually, fixed in https://github.com/StackExchange/StackExchange.Redis/commit/d6a734c5a43dfa680b74ffbad4d5833a69d33bd9

Recommend course of action is to update to https://github.com/StackExchange/StackExchange.Redis/releases/tag/1.1.605

We were on 1.1.603.

@mgravell thanks and sorry for misleading.

Thanks for the fix!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nareshkhatri81 picture nareshkhatri81  ·  5Comments

Moinuddin147 picture Moinuddin147  ·  6Comments

wreckedpc picture wreckedpc  ·  3Comments

BrennanConroy picture BrennanConroy  ·  6Comments

KamranShahid picture KamranShahid  ·  5Comments