{"record":{"id":"94f2dc5bdf0c2fcd","repo":"dotnet/wpf","slug":"property-data-must-be-a-non-reference-variant-compatible","errorCode":null,"errorMessage":"Property data must be a non-reference variant compatible type.","messagePattern":"Property data must be a non-reference variant compatible type\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/ExtendedProperty.cs","lineNumber":204,"sourceCode":"            }\n            else if (type.IsArray)\n            {\n                Type elementType = type.GetElementType();\n                if (elementType.IsValueType && type.GetArrayRank() == 1)\n                {\n                    //\n                    // copy the array memebers, which we know are copy\n                    // on assignment value types\n                    //\n                    Array newArray = Array.CreateInstance(elementType, ((Array)_value).Length);\n                    Array.Copy((Array)_value, newArray, ((Array)_value).Length);\n                    return new ExtendedProperty(guid, newArray);\n                }\n            }\n            //\n            // we didn't find a type we expect, throw\n            //\n            throw new InvalidOperationException(SR.InvalidDataTypeForExtendedProperty);\n        }\n\n\n        private Guid _id;                // id of attribute\n        private object _value;             // data in attribute\n    }\n}\n","sourceCodeStart":186,"sourceCodeEnd":212,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/ExtendedProperty.cs#L186-L212","documentation":"When cloning (copying) an ExtendedProperty, Clone validates that the stored value is of a type it can deep-copy (string, primitive types, arrays of them, etc.). If the value's runtime type is not a non-reference, variant-compatible type the copy falls through to `throw new InvalidOperationException(SR.InvalidDataTypeForExtendedProperty)` — 'Property data must be a non-reference variant compatible type.'","triggerScenarios":"Storing a custom reference type (e.g. a class instance, List<T>, or arbitrary object) as an ExtendedProperty value and then cloning the owning object — e.g. cloning a Stroke or ContextNode that carries the property, or round-tripping through ink serialization APIs that clone properties.","commonSituations":"Attaching rich business objects to ink strokes via AddPropertyData; data persisted by another app version with an unexpected value type; corrupted or hand-edited ISF payloads whose property data doesn't match the declared type.","solutions":["Store only serializable, variant-compatible values: strings, primitives (int, double, bool, DateTime, etc.) and arrays of these.","Convert custom objects to a supported representation (e.g. byte[] or string, such as XML/JSON) before adding as an extended property.","Wrap the clone operation in try/catch for InvalidOperationException and fall back to re-attaching properties manually.","Validate value types when adding property data so invalid data never enters the collection."],"exampleFix":"// before\nstroke.AddPropertyData(myCustomId, new MyMetadata { X = 1 }); // clone later throws\n// after\nstroke.AddPropertyData(myCustomId, Encoding.UTF8.GetBytes(JsonSerializer.Serialize(metadata)));","handlingStrategy":"validation","validationCode":"static bool IsCloneablePropertyValue(object v) =>\n    v == null || v is string || v is byte[] ||\n    v is int || v is long || v is short || v is byte ||\n    v is double || v is float || v is bool || v is char ||\n    v is DateTime || v is decimal || v is Guid;","typeGuard":"static bool IsReferenceTypeValue<T>(object v) => v is T && !(v is string || v is byte[]);","tryCatchPattern":"try { var clone = original.Clone(); }\ncatch (InvalidOperationException) { /* re-attach property data manually */ }","preventionTips":["Store only primitives/strings/byte[] as extended property values","Serialize custom objects to byte[] or JSON before attaching","Test clone/serialize round-trips for every property type you use"],"tags":["wpf","ink","extendedproperty","clone","invalidoperationexception","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}