dotnet/wpf · error · InvalidOperationException

ISF Operation Failed

Error message

ISF Operation Failed

What it means

After attempting to decompress an ISF property blob the result was null, meaning property decompression failed; the library throws the generic 'ISF Operation Failed' InvalidOperationException to avoid exposing details of the failure to potential attackers.

Solutions

  1. Recover the ink from the original source or re-save it with a working WPF application
  2. Inspect the property blob header byte and length for validity before deserialization
  3. Catch InvalidOperationException around attribute/property deserialization and drop only the affected property

Example fix

// before
var attr = StylusPointPropertyIdsFromIsf(blob); // throws ISF Operation Failed
// after
try { attr = Parse(blob); } catch (InvalidOperationException) { attr = DefaultAttributes; }
Defensive patterns

Strategy: try-catch

Validate before calling

if (blob == null || blob.Length < 2) return DefaultAttributes;

Type guard

bool HasValidPropertyHeader(byte[] b) => b is { Length: >= 2 } && (b[0] & 0x40) == 0;

Try / catch

try { attr = DecodeAttributes(blob); } catch (InvalidOperationException) { attr = DefaultAttributes; }

Prevention

When it happens

Trigger: Deserializing ISF drawing attributes / custom properties where the compressed property blob is invalid, e.g. bad algorithm byte or truncated payload fed into AlgoModule.DecompressPropertyData.

Common situations: Corrupt or hand-modified .isf files; ink metadata copied across incompatible applications; partially downloaded/truncated ink streams.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/Compress.cs:158

        /// DecompressPropertyData - decompresses a byte[] representing property data (such as DrawingAttributes.Color)
        /// </summary>
        /// <param name="input">The byte[] to decompress</param>
#endif
        internal static byte[] DecompressPropertyData(byte[] input)
        {
#if OLD_ISF
            //
            // lock to prevent multi-threaded vulnerabilities 
            //
            lock (_compressSync)
            {
#endif
                if (input == null)
                {
                    //we don't raise any information that could be used to attack our ISF code
                    //a simple 'ISF Operation Failed' is sufficient since the user can't do 
                    //anything to fix bogus ISF
                    throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage(SR.DecompressPropertyFailed));
                }

                byte[] data = AlgoModule.DecompressPropertyData(input);
#if OLD_ISF
                uint size = 0;
                byte algo = 0;
                int hr = MS.Win32.Penimc.UnsafeNativeMethods.IsfDecompressPropertyData(input, (uint)input.Length, ref size, null, ref algo);
                if (0 == hr)
                {
                    byte[] data2 = new byte[size];
                    hr = MS.Win32.Penimc.UnsafeNativeMethods.IsfDecompressPropertyData(input, (uint)input.Length, ref size, data2, ref algo);
                    if (0 == hr)
                    {

                        if (data.Length != data2.Length)
                        {
                            throw new InvalidOperationException("MAGIC EXCEPTION: Property bytes length when decompressed didn't match with new uncompression");
                        }

View on GitHub (pinned to 81131a70a4)