dotnet/wpf · error · ArgumentNullException
SR.SCEraseShape
Error message
SR.SCEraseShape
What it means
StrokeCollection.Erase(IEnumerable<Point> eraserPath, StylusShape eraserShape) requires a non-null eraser shape; a null shape throws ArgumentNullException whose message is SR.SCEraseShape. The shape defines the tip geometry (e.g. rectangle/ellipse) of the erasing stroke.
Solutions
- Construct a shape before calling: new EllipseStylusShape(w, h) or RectangleStylusShape
- Guard: if (eraserShape == null) use a default shape
- Initialize the tool state so the shape always exists when erasing is enabled
Example fix
// before strokes.Erase(path, currentShape); // currentShape may be null // after var shape = currentShape ?? new EllipseStylusShape(10, 10); strokes.Erase(path, shape);
Defensive patterns
Strategy: type-guard
Validate before calling
if (eraserShape == null) eraserShape = new EllipseStylusShape(10, 10);
Type guard
bool HasShape(StylusShape s) => s != null;
Try / catch
try { strokes.Erase(path, shape); } catch (ArgumentNullException) { strokes.Erase(path, new EllipseStylusShape(10, 10)); } Prevention
- Initialize tool shapes eagerly when the eraser tool is activated
- Use non-nullable StylusShape fields with defaults
- Never lazily create shapes during input handling
When it happens
Trigger: Calling the shaped Erase overload with eraserShape == null, e.g. a StylusShape field never initialized, or a settings lookup that returned null when the eraser type is unknown.
Common situations: Custom eraser tools where the shape is created lazily on first stylus input but the erase call happens first; deserialized tool configuration missing the shape; refactors replacing a default shape with a nullable one.
Related errors
- SR.SCErasePath
- SR.EventArgIsNull
- anchorLocator.Parts
- ArgumentNullException (buffer/sourceBuffer was IntPtr.Zero)
- ArgumentNullException: handle
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ed9e4ca76c49d97b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection2.cs:318
{
if (!bounds.IsEmpty)
{
Erase(new Point[4] { bounds.TopLeft, bounds.TopRight, bounds.BottomRight, bounds.BottomLeft });
}
}
/// <summary>
/// Erases all ink hit by the contour of an erasing stroke
/// </summary>
/// <param name="eraserShape">Shape of the eraser</param>
/// <param name="eraserPath">a path making the spine of the erasing stroke </param>
public void Erase(IEnumerable<Point> eraserPath, StylusShape eraserShape)
{
// Check the input parameters
if (eraserShape == null)
{
throw new System.ArgumentNullException(SR.SCEraseShape);
}
if (eraserPath == null)
{
throw new System.ArgumentNullException(SR.SCErasePath);
}
if (IEnumerablePointHelper.GetCount(eraserPath) == 0)
{
return;
}
ErasingStroke erasingStroke = new ErasingStroke(eraserShape, eraserPath);
for (int i = 0; i < this.Count; i++)
{
Stroke stroke = this[i];
List<StrokeIntersection> intersections = new List<StrokeIntersection>();
erasingStroke.EraseTest(StrokeNodeIterator.GetIterator(stroke, stroke.DrawingAttributes), intersections);
StrokeCollection eraseResult = stroke.Erase(intersections.ToArray());View on GitHub (pinned to 81131a70a4)