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

  1. Check the active strategy's capabilities before paging: strategy.GetCapabilities().HasFlag(ContainerCacheCapabilities.AsyncEnumeration).
  2. Switch to a cache strategy that supports AsyncEnumeration (e.g. local/container cache or a Redis strategy configured with keyspace enumeration).
  3. If the strategy truly cannot enumerate, replace pagination with direct key-based lookups (GetAsync with known keys) or maintain your own index of keys.
  4. 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

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)