Back to Redis

Error handling

content/develop/clients/dotnet/error-handling.md

latest4.5 KB
Original Source

NRedisStack uses exceptions to signal errors. Code examples in the documentation often omit error handling for brevity, but it is essential in production code. This page explains how NRedisStack's error handling works and how to apply common error handling patterns.

For an overview of error types and handling strategies, see [Error handling]({{< relref "/develop/clients/error-handling" >}}). See also [Production usage]({{< relref "/develop/clients/dotnet/produsage" >}}) for more information on connection management, timeouts, and other aspects of app reliability.

Exception types

NRedisStack throws exceptions to signal errors. Common exception types include:

ExceptionWhen it occursRecoverableRecommended action
RedisConnectionExceptionConnection refused or lostRetry with backoff or fall back
RedisTimeoutExceptionOperation exceeded timeoutRetry with backoff
RedisCommandExceptionInvalid command or argumentsFix the command or arguments
RedisServerExceptionInvalid operation on serverFix the operation or data

See [Categories of errors]({{< relref "/develop/clients/error-handling#categories-of-errors" >}}) for a more detailed discussion of these errors and their causes.

Applying error handling patterns

The [Error handling]({{< relref "/develop/clients/error-handling" >}}) overview describes four main patterns. The sections below show how to implement them in NRedisStack:

Pattern 1: Fail fast

Catch specific exceptions that represent unrecoverable errors and re-throw them (see [Pattern 1: Fail fast]({{< relref "/develop/clients/error-handling#pattern-1-fail-fast" >}}) for a full description):

csharp
using NRedisStack;
using StackExchange.Redis;

var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();

try {
    var result = db.StringGet("key");
} catch (RedisCommandException) {
    // This indicates a bug in the code, such as using
    // StringGet on a list key.
    throw;
}

Pattern 2: Graceful degradation

Catch specific errors and fall back to an alternative, where possible (see [Pattern 2: Graceful degradation]({{< relref "/develop/clients/error-handling#pattern-2-graceful-degradation" >}}) for a full description):

csharp
try {
    var cachedValue = db.StringGet(key);
    return cachedValue.ToString();
} catch (RedisConnectionException) {
    logger.LogWarning("Cache unavailable, using database");

    // Fallback to database
    return database.Get(key);
}

Pattern 3: Retry with backoff

Retry on temporary errors such as timeouts (see [Pattern 3: Retry with backoff]({{< relref "/develop/clients/error-handling#pattern-3-retry-with-backoff" >}}) for a full description):

csharp
const int maxRetries = 3;
int retryDelay = 100;

for (int attempt = 0; attempt < maxRetries; attempt++) {
    try {
        return db.StringGet(key).ToString();
    } catch (RedisTimeoutException) {
        if (attempt < maxRetries - 1) {
            Thread.Sleep(retryDelay);
            retryDelay *= 2;  // Exponential backoff
        } else {
            throw;
        }
    }
}

See also [Timeouts]({{< relref "/develop/clients/dotnet/produsage#timeouts" >}}) for more information on configuring timeouts in NRedisStack.

Pattern 4: Log and continue

Log non-critical errors and continue (see [Pattern 4: Log and continue]({{< relref "/develop/clients/error-handling#pattern-4-log-and-continue" >}}) for a full description):

csharp
try {
    db.StringSet(key, value, TimeSpan.FromSeconds(3600));
} catch (RedisConnectionException) {
    logger.LogWarning($"Failed to cache {key}, continuing without cache");
    // Application continues normally
}

Async error handling

Error handling works the usual way with async/await, as shown in the example below:

csharp
using NRedisStack;
using StackExchange.Redis;

var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();

async Task<string> GetWithFallbackAsync(string key) {
    try {
        var result = await db.StringGetAsync(key);
        if (result.HasValue) {
            return result.ToString();
        }
    } catch (RedisConnectionException) {
        logger.LogWarning("Cache unavailable");
        return await database.GetAsync(key);
    }
    
    return await database.GetAsync(key);
}

See also

  • [Error handling]({{< relref "/develop/clients/error-handling" >}})
  • [Production usage]({{< relref "/develop/clients/dotnet/produsage" >}})