JeffreySu/WeiXinMPSDK · error · NotSupportedException
缓存策略 不支持枚举,请先检查 GetCapabilities()。
Error message
缓存策略 {strategy.GetType().Name} 不支持枚举,请先检查 GetCapabilities()。 What it means
GetPageAsync requires the cache strategy to support AsyncEnumeration. Before paginating, it checks strategy.GetCapabilities() and throws NotSupportedException if the ContainerCacheCapabilities.AsyncEnumeration flag is absent. This guards against strategies (e.g. some distributed caches) that cannot enumerate all keys.
Solutions
- Check the active strategy's capabilities before paging: strategy.GetCapabilities().HasFlag(ContainerCacheCapabilities.AsyncEnumeration).
- Switch to a cache strategy that supports AsyncEnumeration (e.g. local/container cache or a Redis strategy configured with keyspace enumeration).
- If the strategy truly cannot enumerate, replace pagination with direct key-based lookups (GetAsync with known keys) or maintain your own index of keys.
- Register a custom strategy implementation that implements GetAllAsync and declares the AsyncEnumeration capability.
Example fix
// before
var page = await cache.GetPageAsync<MyBag>(strategy, 1, 20);
// after
if (strategy.GetCapabilities().HasFlag(ContainerCacheCapabilities.AsyncEnumeration))
{
var page = await cache.GetPageAsync<MyBag>(strategy, 1, 20);
}
else
{
var item = await strategy.GetAsync<MyBag>(key); // key-based access instead
} Defensive patterns
Strategy: validation
Validate before calling
var caps = strategy.GetCapabilities();
if (!caps.HasFlag(ContainerCacheCapabilities.AsyncEnumeration))
throw new InvalidOperationException($"{strategy.GetType().Name} cannot enumerate; use key-based GetAsync instead."); Try / catch
try
{
var page = await GetPageAsync<T>(strategy, pageIndex, pageSize, ct);
}
catch (NotSupportedException ex)
{
Log(ex.Message);
// fall back to key-based access
} Prevention
- Check GetCapabilities() of any custom or swapped cache strategy before using paged APIs.
- Document which cache backends your app requires (enumeration-capable) in deployment config.
- Add an integration test that calls paged APIs against the production cache strategy.
When it happens
Trigger: Calling ContainerCacheExtensions/GetPageAsync (or a paged helper) with a cache strategy whose GetCapabilities() does not include ContainerCacheCapabilities.AsyncEnumeration.
Common situations: Switching cache containers (e.g. from local MemoryCache to a Redis/distributed strategy) at runtime or via config without verifying the new strategy supports enumeration; using a custom ICacheStrategyImplementation that omitted the AsyncEnumeration capability.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/427cb62578fd9fa7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin/Senparc.Weixin/Cache/ContainerCacheCapabilities.cs:108
this IContainerCacheStrategy strategy,
int offset,
int pageSize,
CancellationToken cancellationToken = default)
where TBag : IBaseContainerBag
{
if (offset < 0)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if (pageSize <= 0)
{
throw new ArgumentOutOfRangeException(nameof(pageSize));
}
if (!strategy.Supports(ContainerCacheCapabilities.AsyncEnumeration))
{
throw new NotSupportedException($"缓存策略 {strategy.GetType().Name} 不支持枚举,请先检查 GetCapabilities()。");
}
cancellationToken.ThrowIfCancellationRequested();
var all = await strategy.GetAllAsync<TBag>().ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
var page = all.OrderBy(item => item.Key, StringComparer.Ordinal)
.Skip(offset)
.Take(pageSize)
.ToList();
return new ContainerCachePage<TBag>(page, offset, all.Count);
}
}
}
View on GitHub (pinned to be573f6f94)