{"record":{"id":"f135fa8dd048ecaa","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-wrappedcacheprov","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'wrappedCacheProvider')","messagePattern":"Value cannot be null\\. \\(Parameter 'wrappedCacheProvider'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Caching/AsyncSerializingCacheProvider.cs","lineNumber":22,"sourceCode":"/// <summary>\n/// 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\" />.\n/// </summary>\n/// <typeparam name=\"TSerialized\">The type of serialized objects to be placed in the cache.</typeparam>\npublic class AsyncSerializingCacheProvider<TSerialized> : IAsyncCacheProvider\n{\n    private readonly IAsyncCacheProvider<TSerialized> _wrappedCacheProvider;\n    private readonly ICacheItemSerializer<object, TSerialized> _serializer;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"AsyncSerializingCacheProvider{TSerialized}\"/> class.\n    /// </summary>\n    /// <param name=\"wrappedCacheProvider\">The wrapped cache provider.</param>\n    /// <param name=\"serializer\">The serializer.</param>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"wrappedCacheProvider\"/> is <see langword=\"null\"/>.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"serializer\"/> is <see langword=\"null\"/>.</exception>\n    public AsyncSerializingCacheProvider(IAsyncCacheProvider<TSerialized> wrappedCacheProvider, ICacheItemSerializer<object, TSerialized> serializer)\n    {\n        _wrappedCacheProvider = wrappedCacheProvider ?? throw new ArgumentNullException(nameof(wrappedCacheProvider));\n        _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));\n    }\n\n    /// <summary>\n    /// Gets a value from the cache asynchronously.\n    /// </summary>\n    /// <param name=\"key\">The cache key.</param>\n    /// <param name=\"cancellationToken\">The cancellation token.</param>\n    /// <param name=\"continueOnCapturedContext\">Whether async calls should continue on a captured synchronization context.</param>\n    /// <returns>\n    /// A <see cref=\"Task{TResult}\" /> promising as Result a tuple whose first element is a value indicating whether\n    /// the key was found in the cache, and whose second element is the value from the cache (null if not found).\n    /// </returns>\n    public async Task<(bool, object?)> TryGetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext)\n    {\n        (bool cacheHit, TSerialized? objectToDeserialize) = await _wrappedCacheProvider.TryGetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);\n        return (cacheHit, cacheHit ? _serializer.Deserialize(objectToDeserialize) : null);\n    }","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/AsyncSerializingCacheProvider.cs#L4-L40","documentation":"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.","triggerScenarios":"Calling new AsyncSerializingCacheProvider<Byte[]>(null, serializer) or passing a wrapped provider field that resolved to null from DI.","commonSituations":"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.","solutions":["Pass a non-null IAsyncCacheProvider<TSerialized> as the wrapped provider.","Verify the inner provider resolved from DI before constructing the serializer wrapper.","Null-check at the call site to surface which registration is missing."],"exampleFix":"// before\nvar cp = new AsyncSerializingCacheProvider<byte[]>(null, serializer);\n// after\nvar inner = new RedisCacheProvider<byte[]>(connection);\nvar cp = new AsyncSerializingCacheProvider<byte[]>(inner, serializer);","handlingStrategy":"validation","validationCode":"ArgumentNullException.ThrowIfNull(wrappedCacheProvider);\nvar cp = new AsyncSerializingCacheProvider<TSerialized>(wrappedCacheProvider, serializer);","typeGuard":"static bool HasInner<T>(IAsyncCacheProvider<T>? p) => p is not null;","tryCatchPattern":"try { var cp = new AsyncSerializingCacheProvider<byte[]>(inner, serializer); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"wrappedCacheProvider\") { /* construct inner provider or fail */ }","preventionTips":["Construct the inner provider at the composition root and null-check it.","Register the inner IAsyncCacheProvider<TSerialized> in DI and assert resolution.","Avoid connection-dependent factories that return null on failure."],"tags":["caching","argumentnullexception","null-argument","polly-v7","serializing-cache-provider"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}