dotnet/wpf · error · ArgumentException

SR.InvalidStream

Error message

SR.InvalidStream

What it means

DecodeRawISF throws this ArgumentException when the first uint decoded from the ISF input stream is not the expected ISF tag value (0x00). It is a guard that the byte stream actually begins with a valid ISF structure rather than arbitrary bytes. The library throws instead of silently misparsing corrupt or non-ISF data.

Solutions

  1. Verify the stream is positioned at the start of the ISF data (stream.Position = 0 / seek to 0 before decoding).
  2. Confirm the data is actually ISF (e.g. produced by StrokeCollectionSerializer.Save) and not another format such as GIF or PNG.
  3. Regenerate the ISF payload from the source application to rule out truncation or corruption in transit.
  4. Wrap decoding in try/catch for ArgumentException and treat the stream as invalid/unparseable ink.

Example fix

// before
var ink = StrokeCollectionSerializer.DecodeISF(someStream);
// after
someStream.Position = 0;
if (!isPlausibleIsf(someStream)) throw new InvalidDataException("Not ISF data");
someStream.Position = 0;
var ink = StrokeCollectionSerializer.DecodeISF(someStream);
Defensive patterns

Strategy: validation

Validate before calling

bool IsPlausibleIsf(Stream s) { if (s.Length < 8) return false; long pos = s.Position; s.Position = 0; var buf = new byte[8]; s.Read(buf, 0, 8); s.Position = pos; return buf[0] == 0; }

Try / catch

try { stream.Position = 0; return StrokeCollectionSerializer.DecodeISF(stream); } catch (ArgumentException ex) { logger.Warn(ex, "Invalid ISF stream header"); return null; }

Prevention

When it happens

Trigger: Calling StrokeCollectionSerializer.DecodeISF (or InkSerializer.Decode) on a stream whose first 4 bytes do not decode to ISF tag 0x00 — e.g. a stream positioned mid-file, a PNG/GIF passed as ISF, or an empty/garbage byte array.

Common situations: Passing a file stream opened without rewinding to position 0 after writing; feeding a serialized format other than ISF (e.g. base64 of an image); loading ISF saved by a different/older ink implementation with a different header.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/InkSerializer.cs:342

                throw new InvalidOperationException(ISFDebugMessage("ISF decoder cannot operate on non-empty ink container"));
            }
#if OLD_ISF
            //
            // store a compressor reference at this scope, if it is needed (if there is a compresson header) and
            // therefore instanced during this routine, we will dispose of it
            // in the finally block
            //
            Compressor compressor = null;

            try
            {
#endif

            // First read the isfTag
            uint uiTag;
            uint localBytesDecoded = SerializationHelper.Decode(inputStream, out uiTag);
            if (0x00 != uiTag)
                throw new ArgumentException(SR.InvalidStream);

            // Now read the size of the stream
            localBytesDecoded = SerializationHelper.Decode(inputStream, out remainingBytesInStream);
            ISFDebugTrace("Decoded Stream Size in Bytes: " + remainingBytesInStream.ToString());
            if (0 == remainingBytesInStream)
                return;

            while (0 < remainingBytesInStream)
            {
                bytesDecodedInCurrentTag = 0;

                // First read the isfTag
                localBytesDecoded = SerializationHelper.Decode(inputStream, out uiTag);
                isfTag = (KnownTagCache.KnownTagIndex)uiTag;
                if (remainingBytesInStream >= localBytesDecoded)
                    remainingBytesInStream -= localBytesDecoded;
                else
                {

View on GitHub (pinned to 81131a70a4)