AvaloniaUI/Avalonia · error · ObjectDisposedException

PathMarkupParser

Error message

PathMarkupParser

What it means

Thrown by ThrowIfDisposed (called from Parse, SetFillRule, CreateFigure, and every Add* method) when the parser has already been disposed or its _geometryContext has been nulled. Dispose(true) sets _isDisposed and nulls _geometryContext, so any subsequent use is rejected.

Source

Thrown at src/Avalonia.Base/Media/PathMarkupParser.cs:614

                command = default;
                relative = false;
                return false;
            }
            var c = span[0];
            if (!s_commands.TryGetValue(char.ToUpperInvariant(c), out command))
            {
                throw new InvalidDataException("Unexpected path command '" + c + "'.");
            }
            relative = char.IsLower(c);
            span = span.Slice(1);
            return true;
        }

        [MemberNotNull(nameof(_geometryContext))]
        private void ThrowIfDisposed()
        {
            if (_isDisposed || _geometryContext is null)
                throw new ObjectDisposedException(nameof(PathMarkupParser));
        }
    }
}

View on GitHub (pinned to 11c5427268)

Solutions

  1. Create a fresh PathMarkupParser per parse operation rather than reusing a disposed instance.
  2. Make sure the using/Dispose scope encloses all Parse calls you need.
  3. Do not dispose the StreamGeometryContext before finishing all writes through the parser.

Example fix

// before
using (var parser = new PathMarkupParser(ctx))
{
    parser.Parse(first);
}
parser.Parse(second); // throws ObjectDisposedException

// after
foreach (var data in new[] { first, second })
{
    using var parser = new PathMarkupParser(ctx);
    parser.Parse(data);
}
Defensive patterns

Strategy: validation

Validate before calling

if (parser is IDisposable { } d) { /* don't reuse after dispose */ }
// Track a _disposed flag in your own code and re-create the parser per parse.

Try / catch

try { parser.Parse(data); }
catch (ObjectDisposedException) { /* re-create parser + context and retry once */ }

Prevention

When it happens

Trigger: Calling parser.Parse(...) after the parser was disposed (e.g. after leaving a 'using var parser = ...' block), or reusing a parser whose owning geometry context was closed/disposed.

Common situations: Using the parser inside a using block and then calling Parse again outside it; sharing a parser field across operations where one path disposes it; nesting geometry Open()/Dispose() scopes incorrectly.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/fe80006bb1ee2c1e. Report an issue: GitHub.