dotnet/wpf · error · ArgumentException

Unrecognized Stroke in Stroke.Invalidated event arguments.

Error message

Unrecognized Stroke in Stroke.Invalidated event arguments.

What it means

Renderer.OnStrokeInvalidated throws ArgumentException (SR.UnknownStroke1) when a Stroke.Invalidated event fires from a stroke that has no entry in the Renderer's _visuals map. The renderer caches a StrokeVisual per stroke; invalidated strokes must be ones it renders.

Solutions

  1. Stop holding/mutating Stroke references after removing them from the rendered collection
  2. Attach strokes to only one Renderer at a time
  3. Re-add the stroke to the StrokeCollection before mutating it if edits are intended
  4. Guard mutations with a check that the stroke belongs to the live collection

Example fix

// before
stroke.StylusPoints = newPoints; // stroke already removed from collection
// after
if (strokeCollection.Contains(stroke)) { stroke.StylusPoints = newPoints; }
Defensive patterns

Strategy: validation

Validate before calling

// Only mutate strokes that are still in the rendered collection
if (strokeCollection.Contains(stroke)) stroke.StylusPoints = newPoints;

Type guard

bool IsTrackedStroke(StrokeCollection c, Stroke s) => c?.Contains(s) == true;

Try / catch

try { stroke.StylusPoints = newPoints; }
catch (ArgumentException) { /* stroke no longer tracked - drop edit */ }

Prevention

When it happens

Trigger: Modifying a Stroke (points, drawing attributes) that is not attached to this Renderer — e.g. a stroke removed from the collection but still referenced, or a stroke shared across renderers where one renderer never tracked it.

Common situations: Retaining Stroke references after removing them from a StrokeCollection and mutating them later, sharing strokes between multiple InkCanvases/renderers, background thread mutations after detach.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/Renderer.cs:481

                {
                    throw new System.ArgumentException(SR.UnknownStroke3);
                }
            }
        }

        /// <summary>
        /// Stroke Invalidated event handler
        /// </summary>
        private void OnStrokeInvalidated(object sender, EventArgs eventArgs)
        {
            System.Diagnostics.Debug.Assert(_strokes.IndexOf(sender as Stroke) != -1);

            // Find the visual associated with the changed stroke.
            StrokeVisual visual;
            Stroke stroke = (Stroke)sender;
            if (!_visuals.TryGetValue(stroke, out visual))
            {
                throw new System.ArgumentException(SR.UnknownStroke1);
            }

            // The original value of IsHighligher and Color are cached in StrokeVisual.
            // if (IsHighlighter value changed or (IsHighlighter == true and not changed and color changed)
            // detach and re-attach the corresponding visual;
            // otherwise Invalidate the corresponding StrokeVisual
            if (visual.CachedIsHighlighter != stroke.DrawingAttributes.IsHighlighter ||
                (stroke.DrawingAttributes.IsHighlighter &&
                    StrokeRenderer.GetHighlighterColor(visual.CachedColor) != StrokeRenderer.GetHighlighterColor(stroke.DrawingAttributes.Color)))
            {
                // The change requires reparenting the visual in the tree.
                DetachVisual(visual);
                AttachVisual(visual, buildingStrokeCollection: false);

                // Update the cached values
                visual.CachedIsHighlighter = stroke.DrawingAttributes.IsHighlighter;
                visual.CachedColor = stroke.DrawingAttributes.Color;
            }

View on GitHub (pinned to 81131a70a4)