dotnet/wpf · error · ArgumentNullException

Value cannot be null. (Parameter 'reader')

Error message

Value cannot be null. (Parameter 'reader')

What it means

LoadFromBinaryReader is the internal deserializer of the compound-file FormatVersion header; it validates its BinaryReader before reading and throws ArgumentNullException (parameter 'reader') when null. It is reached via LoadFromStream, which only passes null if the caller supplied a null stream that slipped past validation.

Solutions

  1. Ensure the Stream passed to LoadFromStream is a valid open Stream, never null
  2. Null-check the stream source (file open result, network response) before loading
  3. If writing a custom loader, never invoke LoadFromBinaryReader with a null reader

Example fix

// before
var fv = FormatVersion.LoadFromStream(GetStream(), out int read);
// after
Stream s = GetStream();
if (s == null) throw new InvalidOperationException("Source stream unavailable");
var fv = FormatVersion.LoadFromStream(s, out int read);
Defensive patterns

Strategy: validation

Validate before calling

if (stream == null) throw new InvalidOperationException("Cannot load FormatVersion: stream is null");
var fv = FormatVersion.LoadFromStream(stream, out int bytesRead);

Type guard

static bool IsUsableStream(Stream s) => s != null && s.CanRead;

Try / catch

try { fv = FormatVersion.LoadFromStream(s, out int n); }
catch (ArgumentNullException ex) { log(ex.ParamName); throw new PackageOpenException("Invalid stream"); }

Prevention

When it happens

Trigger: Indirectly, by calling FormatVersion.LoadFromStream(null, out bytesRead) on a code path where the stream null-check is bypassed; the exception surfaces at the internal LoadFromBinaryReader frame.

Common situations: Opening an OPC/XPS compound file from a stream that came from File.OpenRead or a response body that failed and returned null instead of a Stream.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/FormatVersion.cs:438

#if !PBTCOMPILER
        /// <summary>
        /// Constructor for FormatVersion with information read from the given BinaryReader
        /// </summary>
        /// <param name="reader">BinaryReader where version information is read from</param>
        /// <param name="bytesRead">number of bytes read including padding</param>
        /// <returns>FormatVersion object</returns>
        /// <remarks>
        /// This operation will change the stream pointer. This function is preferred over the 
        /// LoadFromStream as it doesn't leave around Undisposed BinaryReader, which 
        /// LoadFromStream will
        /// </remarks>
        private static FormatVersion LoadFromBinaryReader(BinaryReader reader, out Int32 bytesRead)
        {
            checked
            {
                if (reader == null)
                {
                    throw new ArgumentNullException(nameof(reader));
                }

                FormatVersion ver = new FormatVersion();

                bytesRead = 0;            // Initialize the number of bytes read

                // **************
                //  feature ID
                // **************

                Int32 strBytes;

                ver._featureIdentifier = ContainerUtilities.ReadByteLengthPrefixedDWordPaddedUnicodeString(reader, out strBytes);
                bytesRead += strBytes;

                Int16 major;
                Int16 minor;

View on GitHub (pinned to 81131a70a4)