{"record":{"id":"9696a6f046fa6e72","repo":"AvaloniaUI/Avalonia","slug":"wrong-push-pop-state-order","errorCode":null,"errorMessage":"Wrong Push/Pop state order","messagePattern":"Wrong Push/Pop state order","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Media/ImmediateDrawingContext.cs","lineNumber":243,"sourceCode":"            {\n                if (context._states is null)\n                    throw new ObjectDisposedException(nameof(ImmediateDrawingContext));\n\n                _context = context;\n                _type = type;\n                _matrix = matrix;\n                _level = context._currentLevel += 1;\n                context._states.Push(this);\n            }\n\n            public void Dispose()\n            {\n                if (_type == PushedStateType.None)\n                    return;\n                if (_context._states is null || _context._transformContainers is null)\n                    throw new ObjectDisposedException(nameof(DrawingContext));\n                if (_context._currentLevel != _level)\n                    throw new InvalidOperationException(\"Wrong Push/Pop state order\");\n                _context._currentLevel--;\n                _context._states.Pop();\n                if (_type == PushedStateType.Matrix)\n                    _context.CurrentTransform = _matrix;\n                else if (_type == PushedStateType.Clip)\n                    _context.PlatformImpl.PopClip();\n                else if (_type == PushedStateType.Opacity)\n                    _context.PlatformImpl.PopOpacity();\n                else if (_type == PushedStateType.GeometryClip)\n                    _context.PlatformImpl.PopGeometryClip();\n                else if (_type == PushedStateType.OpacityMask)\n                    _context.PlatformImpl.PopOpacityMask();\n                else if (_type == PushedStateType.MatrixContainer)\n                {\n                    var cont = _context._transformContainers.Pop();\n                    _context._currentContainerTransform = cont.ContainerTransform;\n                    _context.CurrentTransform = cont.LocalTransform;\n                }","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Media/ImmediateDrawingContext.cs#L225-L261","documentation":"PushedState.Dispose throws InvalidOperationException(\"Wrong Push/Pop state order\") when the state's _level does not equal the context's _currentLevel. PushedState objects form a stack; disposing them in non-LIFO order (popping a state while a later-pushed state is still active) corrupts the level counter.","triggerScenarios":"Disposing PushedState disposables out of nesting order — e.g. disposing an outer transform before an inner clip, or partially disposing one branch of a forked draw. Also triggered when a using-declaration is reordered relative to siblings.","commonSituations":"Storing and manually disposing PushedState structs instead of using using; conditional dispose paths that skip a pop; exception paths that dispose states in the wrong sequence.","solutions":["Always dispose PushedState in strict LIFO order using using/using-declarations.","Avoid storing PushedState in fields; keep push/pop lexically nested.","Ensure exception handlers do not reorder disposals."],"exampleFix":"// before - out of order\nvar a = ctx.PushTransform(m);\nvar b = ctx.PushClip(r);\na.Dispose(); // wrong: b is on top\nb.Dispose();\n\n// after\nusing (ctx.PushTransform(m))\nusing (ctx.PushClip(r)) { /* draw */ }","handlingStrategy":"validation","validationCode":"// Always dispose PushedState in LIFO order.\nusing (ctx.PushTransform(m))\nusing (ctx.PushClip(r)) { /* draw */ } // compiler guarantees correct ordering","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use using/using-declarations so the compiler emits LIFO disposal.","Never store and manually dispose PushedState in non-nested order.","Ensure exception paths do not reorder disposal."],"tags":["rendering","drawingcontext","lifecycle","invalidoperation"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}