App-vNext/Polly · error · ArgumentNullException

Value cannot be null. (Parameter 'wrappedCacheProvider')

Error message

Value cannot be null. (Parameter 'wrappedCacheProvider')

What it means

Thrown by the AsyncSerializingCacheProvider<TSerialized> constructor (the non-generic-object variant used to cache any object type) when wrappedCacheProvider is null. This provider decorates an inner cache with serialization; without an inner cache there is nothing to serialize into, so construction is rejected inline via the ?? throw expression.

Source

Thrown at src/Polly/Caching/AsyncSerializingCacheProvider.cs:22

/// <summary>
/// Defines an <see cref="IAsyncCacheProvider"/> which serializes objects of any type in and out of an underlying cache which caches as type <typeparamref name="TSerialized"/>.  For use with asynchronous <see cref="CachePolicy" />.
/// </summary>
/// <typeparam name="TSerialized">The type of serialized objects to be placed in the cache.</typeparam>
public class AsyncSerializingCacheProvider<TSerialized> : IAsyncCacheProvider
{
    private readonly IAsyncCacheProvider<TSerialized> _wrappedCacheProvider;
    private readonly ICacheItemSerializer<object, TSerialized> _serializer;

    /// <summary>
    /// Initializes a new instance of the <see cref="AsyncSerializingCacheProvider{TSerialized}"/> class.
    /// </summary>
    /// <param name="wrappedCacheProvider">The wrapped cache provider.</param>
    /// <param name="serializer">The serializer.</param>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="wrappedCacheProvider"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="serializer"/> is <see langword="null"/>.</exception>
    public AsyncSerializingCacheProvider(IAsyncCacheProvider<TSerialized> wrappedCacheProvider, ICacheItemSerializer<object, TSerialized> serializer)
    {
        _wrappedCacheProvider = wrappedCacheProvider ?? throw new ArgumentNullException(nameof(wrappedCacheProvider));
        _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
    }

    /// <summary>
    /// Gets a value from the cache asynchronously.
    /// </summary>
    /// <param name="key">The cache key.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <param name="continueOnCapturedContext">Whether async calls should continue on a captured synchronization context.</param>
    /// <returns>
    /// A <see cref="Task{TResult}" /> promising as Result a tuple whose first element is a value indicating whether
    /// the key was found in the cache, and whose second element is the value from the cache (null if not found).
    /// </returns>
    public async Task<(bool, object?)> TryGetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext)
    {
        (bool cacheHit, TSerialized? objectToDeserialize) = await _wrappedCacheProvider.TryGetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);
        return (cacheHit, cacheHit ? _serializer.Deserialize(objectToDeserialize) : null);
    }

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Pass a non-null IAsyncCacheProvider<TSerialized> as the wrapped provider.
  2. Verify the inner provider resolved from DI before constructing the serializer wrapper.
  3. Null-check at the call site to surface which registration is missing.

Example fix

// before
var cp = new AsyncSerializingCacheProvider<byte[]>(null, serializer);
// after
var inner = new RedisCacheProvider<byte[]>(connection);
var cp = new AsyncSerializingCacheProvider<byte[]>(inner, serializer);
Defensive patterns

Strategy: validation

Validate before calling

ArgumentNullException.ThrowIfNull(wrappedCacheProvider);
var cp = new AsyncSerializingCacheProvider<TSerialized>(wrappedCacheProvider, serializer);

Type guard

static bool HasInner<T>(IAsyncCacheProvider<T>? p) => p is not null;

Try / catch

try { var cp = new AsyncSerializingCacheProvider<byte[]>(inner, serializer); }
catch (ArgumentNullException ex) when (ex.ParamName == "wrappedCacheProvider") { /* construct inner provider or fail */ }

Prevention

When it happens

Trigger: Calling new AsyncSerializingCacheProvider<Byte[]>(null, serializer) or passing a wrapped provider field that resolved to null from DI.

Common situations: The inner cache provider (e.g. a Redis-backed IAsyncCacheProvider<byte[]>) was never registered; a factory returned null when its connection failed; tests forgot to construct the inner provider.

Related errors


AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13). Data as JSON: /api/errors/f135fa8dd048ecaa. Report an issue: GitHub.