dotnet/wpf · error · InvalidOperationException

Invalid EP in ISF

Error message

Invalid EP in ISF

What it means

Thrown by CustomAttributeSerializer.EncodeAttribute when encoding an ExtendedProperty whose value is of a type that has no ISF serialization rule (the switch over the value's Type fell through to the default case). ISF can only encode known value types (uint/int/byte[], string, etc.); anything else cannot be written to the stream. The library treats this as a programming/data error rather than an environment failure.

Solutions

  1. Find the extended property whose value type is unsupported and remove it before saving, or convert its value to a supported type (int, uint, string, byte[]).
  2. Ensure the value's runtime Type exactly matches one handled by the serializer (e.g. box an int as int, not a convertible double).
  3. If persistence of complex objects is required, serialize the object to a byte[] or string yourself and store that in the extended property.
  4. Persist in GIF instead of ISF if you need extended properties that ISF cannot encode, or keep custom data outside the ink stream.

Example fix

// before
stroke.ExtendedProperties.Add("http://example.com/mydata", new MyCustomObject());
strokeCollection.Save(stream, PersistenceFormat.InkSerializedFormat);
// after
stroke.ExtendedProperties.Add("http://example.com/mydata", Convert.ToBase64String(SerializeToBytes(myObj)));
strokeCollection.Save(stream, PersistenceFormat.InkSerializedFormat);
Defensive patterns

Strategy: validation

Validate before calling

bool IsIsfEncodable(object v) => v is int || v is uint || v is byte || v is byte[] || v is string || v is float || v is double || v is System.Windows.Media.Color;
if (!IsIsfEncodable(value)) throw new ArgumentException($"Value type {value.GetType()} is not ISF-encodable");

Type guard

bool IsIsfEncodable(object v) => v is int or uint or byte or byte[] or string or float or double or System.Windows.Media.Color;

Prevention

When it happens

Trigger: Calling StrokeCollection/Stroke DrawingAttributes or ExtendedProperties save path (Save/EncodeToStream) with a custom extended property whose value type is not one of the ISF-supported types (e.g. a custom class, DateTime, or double not handled by the encoder).

Common situations: Storing arbitrary user objects in Stroke.ExtendedProperties or DrawingAttributes.ExtendedProperties and then serializing the ink to ISF (InkCanvas Save, StrokeCollection.Save with format ISF); code that worked with GIF persistence breaks when switching to ISF where type support is stricter.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/CustomAttributeSerializer.cs:292

                        bw.Write((byte)0);
                    }
                    break;
                }
                case (VarEnum.VT_DECIMAL)://14
                {
                    decimal data = (decimal)value;
                    bw.Write(data);
                    break;
                }
                case (VarEnum.VT_BSTR)://8
                {
                    string data = (string)value;
                    bw.Write( System.Text.Encoding.Unicode.GetBytes( data ) );
                    break;
                }
                default:
                {
                    throw new InvalidOperationException(SR.InvalidEpInIsf);
                }
            }
        }
#if OLD_ISF
        /// <summary>
        /// Encodes a custom attribute to the ISF stream
        /// </summary>
#else
        /// <summary>
        /// Encodes a custom attribute to the ISF stream
        /// </summary>
#endif
        internal static uint EncodeAsISF(Guid id, byte[] data, Stream strm, GuidList guidList, byte compressionAlgorithm, bool fTag)
        {
            uint cbWrite = 0;
            uint cbSize = GuidList.GetDataSizeIfKnownGuid(id);
            Debug.Assert(strm != null);

View on GitHub (pinned to 81131a70a4)