dotnet/wpf · error · ArgumentException

SR.CryptoProviderCanNotMergeBlocks

Error message

SR.CryptoProviderCanNotMergeBlocks

What it means

The constructor also requires cryptoProvider.CanMergeBlocks to be true: this stream's decryption algorithm assumes the CryptoProvider can correctly handle block merging during transform. A provider that cannot merge blocks cannot satisfy the block-size invariants this stream implementation relies on, so ArgumentException (SR.CryptoProviderCanNotMergeBlocks) is thrown for the cryptoProvider parameter.

Solutions

  1. Check cryptoProvider.CanMergeBlocks before construction and choose an alternate provider that supports block merging.
  2. Re-acquire the use license / CryptoProvider from the same rights-management implementation that published the content so block sizes match.
  3. Update the RM SDK/environment to a version whose providers support CanMergeBlocks for this content.
  4. Do not attempt to work around by wrapping the provider; the invariant is required by the stream's block math.

Example fix

// before
var stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider);
// after
if (!cryptoProvider.CanMergeBlocks)
    throw new InvalidOperationException("CryptoProvider cannot merge blocks; incompatible provider.");
var stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider);
Defensive patterns

Strategy: validation

Validate before calling

if (cryptoProvider == null)
    throw new ArgumentNullException(nameof(cryptoProvider));
if (!cryptoProvider.CanMergeBlocks)
    throw new InvalidOperationException("CryptoProvider lacks block-merge support.");
var stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider);

Type guard

bool CanUseForEncryptedStream(System.Security.RightsManagement.CryptoProvider p)
    => p != null && p.CanDecrypt && p.CanMergeBlocks;

Try / catch

try { stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider); }
catch (ArgumentException ex) when (ex.ParamName == "cryptoProvider")
{ /* swap to a merge-capable provider or report incompatibility */ }

Prevention

When it happens

Trigger: Constructing RightsManagementEncryptedStream(baseStream, cryptoProvider) where cryptoProvider.CanMergeBlocks == false — i.e. the provider's block granularity is incompatible with the encrypted stream's block layout.

Common situations: Using a CryptoProvider obtained from a rights-management implementation whose content key/block size differs from what the packaging layer expects; mixing crypto providers across implementations or versions where block-merge support is absent.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/295e2556429fa2ec. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptedStream.cs:286

        //
        //  Internal Methods
        //
        //------------------------------------------------------
        internal RightsManagementEncryptedStream(
                                        Stream baseStream,
                                        CryptoProvider cryptoProvider)
        {
            Debug.Assert(baseStream != null);
            Debug.Assert(cryptoProvider != null);

            if (!cryptoProvider.CanDecrypt )
            {
                throw new ArgumentException(SR.CryptoProviderCanNotDecrypt, nameof(cryptoProvider));            
            }

            if (!cryptoProvider.CanMergeBlocks)
            {
                throw new ArgumentException(SR.CryptoProviderCanNotMergeBlocks, nameof(cryptoProvider));            
            }
            
            _baseStream = baseStream;
            _cryptoProvider = cryptoProvider;

            // Currently BitConverter is implemented as only supporting Little Endian byte order    
            // regardless of the machine type. We would like to make sure that this doesn't change 
            // as we need Little Endian byte order decoding capability on all machines in order to 
            // parse files that travel across different machine types.
            Debug.Assert(BitConverter.IsLittleEndian);

            // initialize stream length
            ParseStreamLength();
        }

        //------------------------------------------------------
        //
        //  Private Methods

View on GitHub (pinned to 81131a70a4)