dotnet/wpf · error · ArgumentException

Read different size from stream then expected

Error message

Read different size from stream then expected

What it means

Thrown by DrawingAttributeSerializer.DecodeAsISF when reading compressed drawing-attribute payload bytes from the source stream: the stream.Read call returned fewer bytes than cbInSize, meaning the ISF payload is truncated or the stream position is wrong. The serializer cannot decompress a partial buffer, so it aborts decoding. It signals corrupt, truncated, or incorrectly formatted ISF (Ink Serialized Format) data rather than an application bug per se.

Solutions

  1. Verify the stream is positioned at the start of the ISF payload (rewind with stream.Position = 0 or Seek) before decoding.
  2. Check that the ISF data source is complete — re-serialize the StrokeCollection or re-download/re-copy the blob.
  3. Validate the byte count of the source against the expected ISF size before calling the decoder.
  4. Wrap decode in try/catch for ArgumentException and surface a clear 'corrupt ink data' message to users instead of crashing.

Example fix

// before: stream may be mid-consumed
var strokes = StrokeCollectionSerializer.DecodeInkStream(stream);
// after: ensure position and full data
stream.Seek(0, SeekOrigin.Begin);
if (stream.Length - stream.Position < declaredSize)
    throw new InvalidDataException("ISF payload truncated");
var strokes = StrokeCollectionSerializer.DecodeInkStream(stream);
Defensive patterns

Strategy: validation

Validate before calling

if (stream == null) throw new ArgumentNullException(nameof(stream));
if (stream.Length - stream.Position < declaredSize)
    throw new InvalidDataException($"ISF payload truncated: need {declaredSize} bytes, have {stream.Length - stream.Position}");

Type guard

bool IsReadable(Stream s, int count) => s != null && s.CanRead && (s.Length - s.Position) >= count;

Try / catch

try { strokes = StrokeCollectionSerializer.DecodeInkStream(stream); }
catch (ArgumentException ex) { log.Warn("Truncated/corrupt ISF data", ex); strokes = new StrokeCollection(); }

Prevention

When it happens

Trigger: DecodeAsISF is given a stream whose remaining length is less than the cbInSize declared in the ISF property header — e.g. a truncated ISF byte array, a stream not rewound to the correct position, or an ISF blob written by a producer with a wrong size field.

Common situations: Loading saved ink (StrokeCollection) from a file or database blob that was truncated by a partial write; passing a stream that another consumer already partially read; hand-crafted or corrupted ISF payloads; cross-version ISF round-trips where sizes were written incorrectly.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/DrawingAttributeSerializer.cs:225

                        if (KnownTagCache.KnownTagIndex.Mantissa == (KnownTagCache.KnownTagIndex)dw)
                        {
                            uint cbInSize;
                            // First thing that is in there is maximumStreamSize of the data
                            cb = SerializationHelper.Decode (stream, out cbInSize);
                            maximumStreamSize -= cb;

                            // in maximumStreamSize is one more than the decoded no
                            cbInSize++;
                            if (cbInSize > maximumStreamSize)
                            {
                                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("ISF size if greater then maximum stream size"));
                            }
                            byte[] in_data = new byte[cbInSize];
							
                            uint bytesRead = (uint) stream.Read (in_data, 0, (int)cbInSize);
                            if (cbInSize != bytesRead)
                            {
                                throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("Read different size from stream then expected"));
                            }

                            byte[] out_buffer = Compressor.DecompressPropertyData (in_data);
                            using (MemoryStream localStream = new MemoryStream(out_buffer))
                            using (BinaryReader rdr = new BinaryReader(localStream))
                            {
                                short sFraction = rdr.ReadInt16();
                                _size += (double)(sFraction / DrawingAttributes.StylusPrecision);

                                maximumStreamSize -= cbInSize;
			                }
                        }
                        else
                        {
                            // Seek it back by cb
                            stream.Seek (-cb, SeekOrigin.Current);
                            maximumStreamSize += cb;
                        }

View on GitHub (pinned to 81131a70a4)