dotnet/wpf · error · FileFormatException

SR.EncryptedDataStreamCorrupt

Error message

SR.EncryptedDataStreamCorrupt

What it means

ParseStreamLength reads a length prefix (the encrypted-stream length stored at the head of the on-disk data) from the base stream. If a nonzero prefix is present but shorter than the legal prefix size (_prefixLengthSize), the file's encrypted data stream is malformed, and a FileFormatException with SR.EncryptedDataStreamCorrupt is thrown. This is a data-corruption signal, not an argument error.

Solutions

  1. Restore the file from a known-good backup or re-acquire/re-download the document — a corrupt prefix cannot be repaired in place.
  2. Verify file integrity (compare size/hash against the source) to confirm the truncation.
  3. Re-create the rights-managed document by republishing the content with RM protection from the original material.
  4. Ensure storage/transfer completes atomically (write to temp then move) to prevent partial writes in the future.
  5. Catch FileFormatException when opening untrusted documents and degrade gracefully with a 'file is corrupt' user message.

Example fix

// before
var stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider);
// after
try
{
    var stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider);
}
catch (FileFormatException)
{
    Console.WriteLine("The rights-managed document's data stream is corrupt; restore from backup.");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity-check file size before opening
var fi = new FileInfo(path);
if (fi.Length < RightsManagementEncryptedStreamMinHeaderSize)
    throw new FileFormatException("File too small to contain a valid encrypted stream header.");

Type guard

bool PlausibleEncryptedStreamLength(FileInfo fi, int prefixLengthSize)
    => fi.Exists && fi.Length >= prefixLengthSize;

Try / catch

try { stream = new RightsManagementEncryptedStream(baseStream, cryptoProvider); }
catch (FileFormatException)
{ /* mark document as corrupt, offer restore/re-download */ }

Prevention

When it happens

Trigger: Opening a rights-managed compound file whose stream-length prefix was truncated or overwritten (partial write, bad sector, faulty tool edit) so that bytesRead > 0 but bytesRead < _prefixLengthSize.

Common situations: Files truncated by interrupted downloads or copy operations; documents damaged by disk errors; hand-edited or incorrectly re-saved compound files; content migrated across tools that mangled the package header.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

                // seek to the beginning of the stream 
                _baseStream.Seek(0, SeekOrigin.Begin);

                // read the size prefix 
                byte[] prefixData = new byte[_prefixLengthSize];
                int bytesRead = PackagingUtilities.ReliableRead
                                            (_baseStream, prefixData, 0, prefixData.Length);

                // decode length data (from the prefix)
                if (bytesRead == 0)
                {
                    // probably a new stream - just assume length is zero
                    _streamOnDiskLength = 0;
                }
                else
                    if (bytesRead < _prefixLengthSize)
                    {
                        // not zero and shorter than legal length == corrupt file
                        throw new FileFormatException(SR.EncryptedDataStreamCorrupt);
                    }
                    else
                    {
                        checked
                        {
                            // This will throw on a negative value so we need not
                            // explicitly check for that
                            _streamOnDiskLength = (long)BitConverter.ToUInt64(prefixData, 0);
                        }
                    }
                _streamCachedLength = _streamOnDiskLength;
            }
        }

        private int InternalRead(long streamPosition, byte[] buffer, int offset, int count)
        {
            // use the explicitly passed in Position or reading in the stream 
            // we do not want to rely and change the real stream position 

View on GitHub (pinned to 81131a70a4)