Error handling
Learn how to handle errors when using StackExchange.Redis.
StackExchange.Redis 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 error handling works in StackExchange.Redis and how to apply common
error handling patterns.
For an overview of error types and handling strategies, see Error handling. See also Production usage for more information on connection management, timeouts, and other aspects of app reliability.
Exception types
StackExchange.Redis throws exceptions to signal errors. Common exception types include:
| Exception | When it occurs | Recoverable | Recommended action |
|---|---|---|---|
RedisConnectionException |
Connection refused or lost | ✅ | Retry with backoff or fall back |
RedisTimeoutException |
Operation exceeded timeout | ✅ | Retry with backoff |
RedisCommandException |
Invalid command or arguments | ❌ | Fix the command or arguments |
RedisServerException |
Invalid operation on server | ❌ | Fix the operation or data |
See Categories of errors for a more detailed discussion of these errors and their causes.
Applying error handling patterns
The Error handling overview
describes four main patterns. The sections below show how to implement them in
StackExchange.Redis:
Pattern 1: Fail fast
Catch specific exceptions that represent unrecoverable errors and re-throw them (see Pattern 1: Fail fast for a full description):
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 for a full description):
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 for a full description):
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
for more information on configuring timeouts in StackExchange.Redis.
Pattern 4: Log and continue
Log non-critical errors and continue (see Pattern 4: Log and continue for a full description):
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:
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);
}