dotnet/wpf · error · ArgumentException

SR.InvalidAttachedAnnotation

Error message

SR.InvalidAttachedAnnotation

What it means

RemoveAttachedAnnotation only removes the exact IAttachedAnnotation instance this HighlightComponent currently holds. Passing any other instance throws ArgumentException with SR.InvalidAttachedAnnotation. The strict identity check keeps the component's range/highlight state consistent with what the manager believes is attached.

Solutions

  1. Keep the original IAttachedAnnotation reference returned at add time and pass that exact instance to RemoveAttachedAnnotation.
  2. Track the live attached annotation per component in your manager layer so removal uses identity, not an equal copy.
  3. Catch ArgumentException and log instead of failing when a best-effort cleanup is intended.
  4. Route removal through AnnotationService/AnnotationComponentManager rather than calling the component directly, so the right instance is resolved.

Example fix

// before
component.RemoveAttachedAnnotation(recreatedAnnotation); // identity mismatch -> throws
// after
if (ReferenceEquals(recreatedAnnotation, liveAnnotation))
    component.RemoveAttachedAnnotation(liveAnnotation);
Defensive patterns

Strategy: validation

Validate before calling

if (ReferenceEquals(attachedAnnotation, liveAttachedAnnotation))
    component.RemoveAttachedAnnotation(liveAttachedAnnotation);

Type guard

bool IsLive(IAttachedAnnotation a, IAttachedAnnotation live) => ReferenceEquals(a, live);

Try / catch

try { component.RemoveAttachedAnnotation(a); }
catch (ArgumentException) { /* not the live instance; resolve via the service */ }

Prevention

When it happens

Trigger: Calling RemoveAttachedAnnotation(attachedAnnotation) with an attachedAnnotation that is not reference-equal to the one previously added — e.g. a re-created IAttachedAnnotation from a reloaded annotation store.

Common situations: Rebuilding attached annotation objects between add and remove (store reload, clone); removing annotations against a different AnnotationService instance than the one that added them; holding serialized/deserialized attached annotations instead of the live instances.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/HighlightComponent.cs:267

            highlightLayer.AddRange(this);
            HighlightBrush = new SolidColorBrush(_background);
            IsHitTestVisible = false;

            //fire trace event
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnnotation, EventTrace.Event.AddAttachedHighlightEnd);
        }

        /// <summary>
        /// Remove an attached annotation from the component
        /// </summary>
        /// <param name="attachedAnnotation">The attached annotation to be removed from the component</param>
        public void RemoveAttachedAnnotation(IAttachedAnnotation attachedAnnotation)
        {
            ArgumentNullException.ThrowIfNull(attachedAnnotation);

            if (attachedAnnotation != _attachedAnnotation)
            {
                throw new ArgumentException(SR.InvalidAttachedAnnotation, nameof(attachedAnnotation));
            }

            Invariant.Assert(_range != null, "null highlight range");

            //fire trace event
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnnotation, EventTrace.Event.RemoveAttachedHighlightBegin);

            //check input data and retrieve the TextContainer
            ITextContainer textContainer = CheckInputData(attachedAnnotation);

            Invariant.Assert(textContainer.Highlights != null, "textContainer.Highlights is null");

            //get AnnotationHighlightLayer in the textContainer
            AnnotationHighlightLayer highlightLayer = textContainer.Highlights.GetLayer(typeof(HighlightComponent)) as AnnotationHighlightLayer;
            Invariant.Assert(highlightLayer != null, "AnnotationHighlightLayer is not initialized");

            //unregister of cargo changes
            _attachedAnnotation.Annotation.CargoChanged -= new AnnotationResourceChangedEventHandler(OnAnnotationUpdated);

View on GitHub (pinned to 81131a70a4)