dotnet/wpf · error · InvalidOperationException

SR.StreamGeometry_NeedBeginFigure

Error message

SR.StreamGeometry_NeedBeginFigure

What it means

ByteStreamGeometryContext.ArcTo appends an arc segment to the current figure of a StreamGeometry. A segment can only be added after BeginFigure has been called; if no figure is open (_currentPathFigureDataOffset == -1) the context throws InvalidOperationException.

Solutions

  1. Call context.BeginFigure(startPoint, isFilled, isClosed) before the first ArcTo.
  2. Check the path-conversion/parsing code so a leading Move command is emitted as BeginFigure.
  3. Guard each geometry-building routine so segments are only emitted when a figure is open.

Example fix

// before
using (var ctx = geometry.Open())
{
    ctx.ArcTo(pt, size, 0, false, SweepDirection.Clockwise, true, false);
}

// after
using (var ctx = geometry.Open())
{
    ctx.BeginFigure(startPoint, true, false);
    ctx.ArcTo(pt, size, 0, false, SweepDirection.Clockwise, true, false);
}
Defensive patterns

Strategy: validation

Validate before calling

bool figureOpen = ctx.GetType().GetProperty("CurrentFigureOpen")?.GetValue(ctx) as bool? ?? true; if (!figureOpen) ctx.BeginFigure(startPoint, true, false);

Try / catch

try { ctx.ArcTo(p, s, 0, false, SweepDirection.Clockwise, true, false); }
catch (InvalidOperationException) { ctx.BeginFigure(start, true, false); ctx.ArcTo(p, s, 0, false, SweepDirection.Clockwise, true, false); }

Prevention

When it happens

Trigger: Calling ArcTo on a StreamGeometryContext obtained from StreamGeometry.Open() before calling BeginFigure, or after the current figure was invalidated (e.g. after Dispose of prior state).

Common situations: Building path geometry programmatically where an arc is the first command; converting path data where the leading 'M' (move) command was dropped or skipped during parsing.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/d7309f5fe9fdf13b. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/ByteStreamGeometryContext.cs:203

            GenericPolyTo(points, 
                          isStroked, 
                          isSmoothJoin, 
                          hasCurves: true,
                          pointCountMultiple: 3,
                          MIL_SEGMENT_TYPE.MilSegmentPolyBezier);
        }

        /// <summary>
        /// ArcTo - append an ArcTo to the current figure.
        /// </summary>
        public override void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection, bool isStroked, bool isSmoothJoin)
        {
            VerifyApi();

            if (_currentPathFigureDataOffset == -1)
            {
                throw new InvalidOperationException(SR.StreamGeometry_NeedBeginFigure);
            }

            FinishSegment();

            MIL_SEGMENT_ARC arcToSegment = new MIL_SEGMENT_ARC
            {
                Type = MIL_SEGMENT_TYPE.MilSegmentArc
            };

            arcToSegment.Flags |= isStroked ? 0 : MILCoreSegFlags.SegIsAGap;
            arcToSegment.Flags |= isSmoothJoin ? MILCoreSegFlags.SegSmoothJoin : 0;
            arcToSegment.Flags |= MILCoreSegFlags.SegIsCurved;
            arcToSegment.BackSize = _lastSegmentSize;

            arcToSegment.Point = point;
            arcToSegment.Size = size;
            arcToSegment.XRotation = rotationAngle;
            arcToSegment.LargeArc = (uint)(isLargeArc ? 1 : 0);

View on GitHub (pinned to 81131a70a4)