AvaloniaUI/Avalonia · error · ObjectDisposedException
PlatformDrawingContext
Error message
PlatformDrawingContext
What it means
Thrown by PopTransformCore when the _transforms stack is null at pop time. The stack is lazily allocated on the first PushTransformCore call; a null stack means no transform was ever pushed (so there is nothing to pop), or the context was already disposed (DisposeCore returns the stack to the pool and nulls the field).
Source
Thrown at src/Avalonia.Base/Media/PlatformDrawingContext.cs:110
protected override void PushEffectCore(IEffect effect, Rect bounds)
{
if (_impl is IDrawingContextImplWithEffects effectImpl)
{
effectImpl.PushEffect(bounds.Inflate(effect.GetEffectOutputPadding()), effect);
}
}
protected override void PopClipCore() => _impl.PopClip();
protected override void PopGeometryClipCore() => _impl.PopGeometryClip();
protected override void PopOpacityCore() => _impl.PopOpacity();
protected override void PopOpacityMaskCore() => _impl.PopOpacityMask();
protected override void PopTransformCore() =>
_impl.Transform =
(_transforms ?? throw new ObjectDisposedException(nameof(PlatformDrawingContext))).Pop();
protected override void PopRenderOptionsCore() => _impl.PopRenderOptions();
protected override void PopTextOptionsCore() => _impl.PopTextOptions();
/// <inheritdoc />
protected override void PopEffectCore()
{
if (_impl is IDrawingContextImplWithEffects effectImpl)
{
effectImpl.PopEffect();
}
}
protected override void DisposeCore()
{
if (_ownsImpl)
_impl.Dispose();View on GitHub (pinned to 11c5427268)
Solutions
- Match every PushTransform with exactly one PopTransform in the same scope.
- Use a try/finally (or 'using (context.PushTransform(...))' if available) so a Pop always runs even on exception.
- Do not call any Draw/Pop method on a DrawingContext after it is disposed.
Example fix
// before
context.PushTransform(matrix);
// ... exception skips the pop ...
context.PopTransform();
// after
context.PushTransform(matrix);
try
{
// draw
}
finally
{
context.PopTransform();
} Defensive patterns
Strategy: validation
Validate before calling
// Maintain a depth counter; only Pop when depth > 0.
int transformDepth = 0;
void SafePush(Matrix m) { context.PushTransform(m); transformDepth++; }
void SafePop() { if (transformDepth > 0) { context.PopTransform(); transformDepth--; } } Try / catch
try { context.PopTransform(); }
catch (ObjectDisposedException) { /* context disposed or no push — reset state */ } Prevention
- Wrap Push/Pop in try/finally so Pop always runs.
- Never Pop without a prior Push on the same context.
When it happens
Trigger: Calling PopTransform() without a matching PushTransform(); or calling PopTransform() after the drawing context has been disposed.
Common situations: Unbalanced transform push/pop in custom render overrides; an early-return or exception path that pops a transform that was never pushed; reusing a disposed DrawingContext.
Related errors
- Not all states are disposed
- Animator has no property specified.
- {item.DebugDisplay} must have a value of type {typeof(Transf
- PathMarkupParser
- glyphRun
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/5f73fd5e90782d8d.
Report an issue: GitHub.