{"record":{"id":"1abc0d4a5126e2ba","repo":"dotnet/wpf","slug":"rop-data-was-incorrectly-serialized","errorCode":null,"errorMessage":"ROP data was incorrectly serialized","messagePattern":"ROP data was incorrectly serialized","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/DrawingAttributeSerializer.cs","lineNumber":541,"sourceCode":"        private static void PersistRasterOperation(DrawingAttributes da, Stream stream, GuidList guidList, ref uint cbData, ref BinaryWriter bw)\n        {\n            // write any non-default RasterOp value that we might have picked up from \n            // V1 interop or by setting IsHighlighter.\n            if (da.RasterOperation != DrawingAttributeSerializer.RasterOperationDefaultV1)\n            {\n                uint ropSize = GuidList.GetDataSizeIfKnownGuid(KnownIds.RasterOperation);\n                if (ropSize == 0)\n                {\n                    throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage(\"ROP data size was not found\"));\n                }\n\n                Debug.Assert(bw != null);\n                cbData += SerializationHelper.Encode(stream, (uint)guidList.FindTag(KnownIds.RasterOperation, true));\n                long currentPosition = stream.Position;\n                bw.Write(da.RasterOperation);\n                if ((uint)(stream.Position - currentPosition) != ropSize)\n                {\n                    throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage(\"ROP data was incorrectly serialized\"));\n                }\n                cbData += ropSize;\n            }\n        }\n#if OLD_ISF\n        /// <Summary>\n        /// Encodes the ExtendedProperties in the ISF stream.\n        /// </Summary>\n#else\n        /// <Summary>\n        /// Encodes the ExtendedProperties in the ISF stream.\n        /// </Summary>\n#endif\n        private static void PersistExtendedProperties(DrawingAttributes da, Stream stream, GuidList guidList, ref uint cbData, ref BinaryWriter bw, byte compressionAlgorithm, bool fTag)\n        {\n            // Now save the extended properties\n            ExtendedPropertyCollection epcClone = da.CopyPropertyData();\n","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/DrawingAttributeSerializer.cs#L523-L559","documentation":"Thrown by PersistRasterOperation after writing the RasterOperation value: the number of bytes actually written to the stream differs from ropSize reported by GetDataSizeIfKnownGuid. The serializer keeps the size table in sync with what it writes, so a mismatch means the writer wrote the wrong amount of data for the ROP value — an internal serialization invariant violation.","triggerScenarios":"EncodeAsISF on DrawingAttributes whose RasterOperation value serializes to a byte count different from the size the GuidList associates with the RasterOperation GUID — typically caused by corrupt/modified GuidList state or custom ROP data inserted with a wrong size.","commonSituations":"Custom ISF code that registered a RasterOperation data size inconsistent with the 4-byte value the serializer writes; debugging/patching internals of the ink serialization stack.","solutions":["Ensure any RasterOperation entry added to the GuidList declares the correct size (4 bytes for the standard ROP value).","Avoid manual manipulation of the GuidList / ISF internals; use the public StrokeCollection.Save API.","Reset DrawingAttributes to standard values (default RasterOperation) before saving to skip the ROP path entirely.","Catch InvalidOperationException around Save and re-throw with the drawing attributes for diagnostics."],"exampleFix":"// before: custom size registered wrongly\nguidList.Add(KnownIds.RasterOperation, size: 2);\n// after: standard ROP value is 4 bytes\nguidList.Add(KnownIds.RasterOperation, size: 4);","handlingStrategy":"try-catch","validationCode":"Debug.Assert(guidList.GetDataSizeIfKnownGuid(KnownIds.RasterOperation) == 4, \"RasterOperation data size must be 4 bytes\");","typeGuard":"bool HasValidRopSize(GuidList g) => g.GetDataSizeIfKnownGuid(KnownIds.RasterOperation) == 4;","tryCatchPattern":"try { collection.Save(stream); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ROP data was incorrectly serialized\")) { /* regenerate GuidList or reset attributes */ }","preventionTips":["Do not manually modify the GuidList or ISF internals.","Keep RasterOperation at its default unless the full V1 encoding path is exercised.","Round-trip test Save/Load in CI to catch serialization drift early."],"tags":["ink","isf","serialization","raster-operation"],"backgroundTag":"internal-invariant-violation","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"}