dotnet/wpf · error · ArgumentNullException

SR.SCErasePath

Error message

SR.SCErasePath

What it means

StrokeCollection.Erase(IEnumerable<Point> eraserPath, StylusShape eraserShape) requires a non-null eraser path; a null path throws ArgumentNullException whose message is SR.SCErasePath. The path is the spine along which the eraser shape is swept to remove strokes. An empty path is a no-op, but null is rejected.

Solutions

  1. Guard: if (eraserPath == null) return; before calling Erase
  2. Ensure the stylus input handler always materializes a point collection, even if empty
  3. Pass an empty collection (which is a no-op) instead of null

Example fix

// before
strokes.Erase(path, shape); // path may be null
// after
if (path != null)
{
    strokes.Erase(path, shape);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (eraserPath == null) return;

Type guard

bool HasPath(IEnumerable<Point> p) => p != null;

Try / catch

try { strokes.Erase(path, shape); } catch (ArgumentNullException) { /* no path captured: skip */ }

Prevention

When it happens

Trigger: Calling the shaped Erase overload with eraserPath == null, e.g. stylus points were never collected, or a nullable point collection variable was passed without a check.

Common situations: Erase triggered before any input points were captured; async processing where the path is produced later; porting code from an overload that accepted null silently.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Ink/StrokeCollection2.cs:322

            }
        }


        /// <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());

                UpdateStrokeCollection(stroke, eraseResult, ref i);
            }
        }

View on GitHub (pinned to 81131a70a4)