Skill v1.0.1
currentAutomated scan100/100+2 new
version: "1.0.1" name: redis-diagnose description: Troubleshoot common StackExchange.Redis.Extensions issues — timeouts, connection failures, serialization problems, pool exhaustion
Redis Diagnose
Diagnose and fix common issues with StackExchange.Redis.Extensions.
When to use
When the user reports:
- Timeout exceptions
- Connection failures
- Serialization errors
- Pool exhaustion
- Pub/Sub messages not being received
- Performance issues
Diagnostic Tree
RedisTimeoutException
Symptoms: StackExchange.Redis.RedisTimeoutException
Check in order:
- SyncTimeout too low — default is 5000ms, increase for slow networks
``csharp config.SyncTimeout = 10000; // 10 seconds ``
- Pool size too small — default 5, increase for high-throughput
``csharp config.PoolSize = 10; ``
- Connection strategy — switch to LeastLoaded if using RoundRobin
``csharp config.ConnectionSelectionStrategy = ConnectionSelectionStrategy.LeastLoaded; ``
- Large values — enable compression to reduce payload size
``csharp services.AddRedisCompression<LZ4Compressor>(); ``
- ThreadPool starvation — check with
ThreadPool.GetAvailableThreads(), increase min threads
RedisConnectionException
Symptoms: SocketClosed, ConnectionFailed
Check:
- Redis server reachable? —
redis-cli -h <host> -p <port> ping - Firewall/NSG rules — port 6379 (or 6380 for TLS) open?
- TLS misconfiguration — if using Ssl=true, check certificate callbacks
- Sentinel misconfiguration — ServiceName must match Redis master name exactly
- Azure Cache for Redis — ensure Managed Identity is configured if not using password
Serialization Errors
Symptoms: JsonException, InvalidOperationException, corrupt data
Check:
- Type mismatch — GetAsync<T> must use same T as AddAsync<T>
- String values are JSON-encoded — "hello" is stored as "\"hello\"", this is by design
- Compression migration — enabling compression makes old (uncompressed) data unreadable
- Error:
InvalidOperationException: Failed to decompress data from Redis - Fix: flush the database or read old data without compression first
- Value type quirk —
GetAsync<int>()returns 0 (not null) for missing keys becausedefault(int)is0. UseGetAsync<int?>()to distinguish missing keys from actual zero values.
Pub/Sub Not Receiving Messages
Check:
- KeyPrefix — channels are automatically prefixed. Don't add prefix manually.
- Serializer mismatch — publisher and subscriber must use the same serializer
- Handler exceptions — check logs for EventId 4001 errors. Handlers that throw don't crash but the message is lost.
- Different connection pools — ensure pub and sub use the same IRedisDatabase instance
Pool Exhaustion / All Connections Down
Symptoms: All operations fail, logs show EventId 1003
Check:
- Pool health — inject
IRedisClientand callclient.ConnectionPoolManager.GetConnectionInformation() - Use health check — register
builder.Services.AddHealthChecks().AddRedisExtensionsHealthCheck()to monitor pool status automatically (returns Healthy/Degraded/Unhealthy) - Redis server overloaded — check
INFO clientson Redis - Network partition — the pool skips disconnected connections automatically and logs warnings
- Dispose pattern — ensure IRedisConnectionPoolManager is not disposed prematurely
IDistributedCache Issues
Symptoms: Data not found, expiration not working, migration issues
Check:
- Registration order —
AddRedisDistributedCache()must be called afterAddStackExchangeRedisExtensions<T>() - KeyPrefix applies — IDistributedCache goes through
IRedisDatabase.Databasewhich usesWithKeyPrefix. Cache keys are prefixed automatically. - Migration from Microsoft provider — hash schema is compatible (
data/absexp/sldexpfields), but key prefix format may differ (this library usesKeyPrefix, Microsoft usesInstanceName) - Sliding expiration not refreshing —
GetandRefreshboth refresh the TTL. Check thatSlidingExpirationwas set inDistributedCacheEntryOptions
Keyed DI Not Resolving
Symptoms: [FromKeyedServices("name")] returns null
Check:
- Config must have a Name —
RedisConfiguration.Namemust be non-empty for keyed registration - Use eager overloads — keyed services are only registered with the overloads that receive
RedisConfigurationdirectly, NOT theFunc<IServiceProvider, ...>overload - Name must match exactly —
[FromKeyedServices("cache")]must matchconfig.Name = "cache"(case-sensitive)
Performance Issues
Check:
- Enable logging — set log level to Debug to see connection selection
``json { "Logging": { "LogLevel": { "StackExchange.Redis.Extensions.Core": "Debug" } } } ``
- Check outstanding commands — pool info shows outstanding count per connection
- Use compression for large objects — LZ4 adds ~1ms latency but reduces network 5-10x
- Use AddAllAsync for bulk writes instead of loop of AddAsync
- Use GetAllAsync for bulk reads (note: requires
HashSet<string>for keys, not arrays)
Logging Reference
| EventId | Level | Meaning | |
|---|---|---|---|
| 1001 | Info | Pool initialized successfully | |
| 1003 | Warning | All connections disconnected — degraded mode | |
| 1006 | Error | Pool initialization failed | |
| 2001 | Error | Connection failed | |
| 2002 | Warning | Connection restored | |
| 4001 | Error | Pub/Sub handler threw exception |
Enable with:
{ "Logging": { "LogLevel": { "StackExchange.Redis.Extensions.Core": "Information" } } }