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
- Call context.BeginFigure(startPoint, isFilled, isClosed) before the first ArcTo.
- Check the path-conversion/parsing code so a leading Move command is emitted as BeginFigure.
- 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
- Always emit BeginFigure as the first operation after StreamGeometry.Open().
- In path parsers, map every leading Move command to BeginFigure and treat segments without a figure as parser bugs.
- Encapsulate geometry building in a helper that tracks figure state.
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
- Animation_Invalid_DefaultValue
- Cannot remove signature from read-only file.
- Image_EncoderNoColorContext
- Image_EncoderNoGlobalMetadata
- Image_EncoderNoGlobalThumbnail
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)