AvaloniaUI/Avalonia · error · ObjectDisposedException
DrawingContext
Error message
DrawingContext
What it means
PushedState.Dispose throws ObjectDisposedException(nameof(DrawingContext)) when _states or _transformContainers is null — i.e. disposing a PushedState whose owning context was already disposed. This is the use-after-dispose guard for the per-push disposable.
Source
Thrown at src/Avalonia.Base/Media/ImmediateDrawingContext.cs:241
internal PushedState(ImmediateDrawingContext context, PushedStateType type, Matrix matrix = default)
{
if (context._states is null)
throw new ObjectDisposedException(nameof(ImmediateDrawingContext));
_context = context;
_type = type;
_matrix = matrix;
_level = context._currentLevel += 1;
context._states.Push(this);
}
public void Dispose()
{
if (_type == PushedStateType.None)
return;
if (_context._states is null || _context._transformContainers is null)
throw new ObjectDisposedException(nameof(DrawingContext));
if (_context._currentLevel != _level)
throw new InvalidOperationException("Wrong Push/Pop state order");
_context._currentLevel--;
_context._states.Pop();
if (_type == PushedStateType.Matrix)
_context.CurrentTransform = _matrix;
else if (_type == PushedStateType.Clip)
_context.PlatformImpl.PopClip();
else if (_type == PushedStateType.Opacity)
_context.PlatformImpl.PopOpacity();
else if (_type == PushedStateType.GeometryClip)
_context.PlatformImpl.PopGeometryClip();
else if (_type == PushedStateType.OpacityMask)
_context.PlatformImpl.PopOpacityMask();
else if (_type == PushedStateType.MatrixContainer)
{
var cont = _context._transformContainers.Pop();
_context._currentContainerTransform = cont.ContainerTransform;View on GitHub (pinned to 11c5427268)
Solutions
- Dispose PushedState values within the context's lifetime (they are returned by using declarations).
- Do not retain PushedState structs beyond the draw call.
- Ensure the context outlives every push/pop pair.
Example fix
// before - leaked state disposed after context gone
PushedState s;
using (var ctx = ...CreateDrawingContext()) { s = ctx.PushTransform(m); }
s.Dispose(); // ObjectDisposedException
// after
using (var ctx = ...CreateDrawingContext())
using (ctx.PushTransform(m)) { /* draw */ } Defensive patterns
Strategy: validation
Validate before calling
// Do not dispose a PushedState after its owning context is disposed.
using (var ctx = CreateContext())
using (var s = ctx.PushTransform(m))
{ /* draw */ } // s disposed here, within ctx lifetime Prevention
- Dispose PushedState values within the context lifetime using using-declarations.
- Never retain PushedState structs beyond the draw call.
- Keep push/pop lexically nested.
When it happens
Trigger: A PushedState disposable outliving its ImmediateDrawingContext: the context's using-block exits (disposing all states), then a previously returned PushedState is disposed again, or a leaked PushedState is disposed after the context was torn down.
Common situations: Storing PushedState structs in fields/closures and disposing them after the render context closed; nested using scopes that leak.
Related errors
- ImmediateDrawingContext
- Wrong Push/Pop state order
- Transform container stack is non-empty
- Unable to obtain ANativeWindow
- TopLevel.InternalView was not expected to be null.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/92f5db54daee3d5e.
Report an issue: GitHub.