{"record":{"id":"14af4cbe498de345","repo":"dotnet/wpf","slug":"isf-decoder-cannot-operate-on-non-empty-ink-container","errorCode":null,"errorMessage":"ISF decoder cannot operate on non-empty ink container","messagePattern":"ISF decoder cannot operate on non-empty ink container","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/InkSerializer.cs","lineNumber":324,"sourceCode":"            uint metricDescriptorTableIndex = 0;\n            uint oldMetricDescriptorTableIndex = 0xFFFFFFFF;\n            uint transformTableIndex = 0;\n            uint oldTransformTableIndex = 0xFFFFFFFF;\n            GuidList guidList = new GuidList();\n            int strokeIndex = 0;\n\n            StylusPointDescription currentStylusPointDescription = null;\n            Matrix currentTabletToInkTransform = Matrix.Identity;\n\n            _strokeDescriptorTable = new System.Collections.Generic.List<StrokeDescriptor>();\n            _drawingAttributesTable = new System.Collections.Generic.List<DrawingAttributes>();\n            _transformTable = new System.Collections.Generic.List<TransformDescriptor>();\n            _metricTable = new System.Collections.Generic.List<MetricBlock>();\n\n            // First make sure this ink is empty\n            if (0 != _coreStrokes.Count || _coreStrokes.ExtendedProperties.Count != 0)\n            {\n                throw new InvalidOperationException(ISFDebugMessage(\"ISF decoder cannot operate on non-empty ink container\"));\n            }\n#if OLD_ISF\n            //\n            // store a compressor reference at this scope, if it is needed (if there is a compresson header) and\n            // therefore instanced during this routine, we will dispose of it\n            // in the finally block\n            //\n            Compressor compressor = null;\n\n            try\n            {\n#endif\n\n            // First read the isfTag\n            uint uiTag;\n            uint localBytesDecoded = SerializationHelper.Decode(inputStream, out uiTag);\n            if (0x00 != uiTag)\n                throw new ArgumentException(SR.InvalidStream);","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/InkSerializedFormat/InkSerializer.cs#L306-L342","documentation":"DecodeRawISF requires the target ink container to be empty before decoding; if _coreStrokes already contains strokes or extended properties, it throws InvalidOperationException. The ISF decoder overwrites the container and refuses to merge into existing ink, so reusing a populated StrokeCollection's internal container is unsupported.","triggerScenarios":"Calling DecodeISF (directly or via StrokeCollectionSerializer) on an InkSerializer whose stroke collection already holds strokes or extended properties — e.g. decoding into a loaded collection a second time.","commonSituations":"Reusing a single StrokeCollection/serializer instance to load multiple ink documents, calling DecodeISF twice on the same object, appending persisted ink to an already-populated collection.","solutions":["Create a fresh StrokeCollection/InkSerializer for each decode operation","Clear extended properties and strokes (or use a new instance) before decoding","Decode into a temporary collection and merge afterwards if combining ink is needed"],"exampleFix":"// before\nserializer.DecodeISF(stream1);\nserializer.DecodeISF(stream2); // throws\n// after\nvar s1 = new StrokeCollectionSerializer(); s1.DecodeISF(stream1);\nvar s2 = new StrokeCollectionSerializer(); s2.DecodeISF(stream2);\nvar combined = new StrokeCollection(s1.Strokes.Concat(s2.Strokes));","handlingStrategy":"type-guard","validationCode":"// only decode into fresh containers\nbool CanDecode(StrokeCollection c) => c.Count == 0 && c.ExtendedProperties.Count == 0;","typeGuard":"bool IsEmptyInkContainer(StrokeCollection c) => c.Count == 0 && c.ExtendedProperties.Count == 0;","tryCatchPattern":"try { serializer.DecodeISF(stream); }\ncatch (InvalidOperationException) { serializer = new StrokeCollectionSerializer(); serializer.DecodeISF(stream); }","preventionTips":["Instantiate a new StrokeCollection/serializer per document","Never reuse a populated collection as a decode target","Merge collections after decoding instead of decoding into existing ink"],"tags":["ink","isf","invalid-state","reuse"],"backgroundTag":"invalid-state-transition","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"}