dotnet/wpf · error · InvalidOperationException

SR.InvalidAttachedAnnotation

Error message

SR.InvalidAttachedAnnotation

What it means

MarkedHighlightComponent.GetDesiredTransform throws InvalidOperationException(SR.InvalidAttachedAnnotation) when _attachedAnnotation is null. The component recalculates marker rendering transforms during layout, which is impossible without an attached annotation, indicating GetDesiredTransform was called on an empty component.

Solutions

  1. Only add MarkedHighlightComponent instances to the visual/layout tree via AddAttachedAnnotation on the AnnotationService.
  2. Detach the component from the adorner layer (RemoveAttachedAnnotation path) before clearing the annotation reference.
  3. Guard custom layout code: skip transform computation if the component has no attached annotation.

Example fix

// before
layer.AddAdorner(markedHighlight); // may layout before annotation attached
// after
markedHighlight.AddAttachedAnnotation(attachedAnnotation);
layer.AddAdorner(markedHighlight);
Defensive patterns

Strategy: validation

Validate before calling

if (markedHighlight.AttachedAnnotation == null) return; // nothing to transform

Type guard

static bool HasAttachedAnnotation(MarkedHighlightComponent c) => c.AttachedAnnotation != null;

Try / catch

try { var t = markedHighlight.GetDesiredTransform(xform); } catch (InvalidOperationException) { t = xform; }

Prevention

When it happens

Trigger: The TextView/layout pipeline calls GetDesiredTransform on a MarkedHighlightComponent before AddAttachedAnnotation ran, or after RemoveAttachedAnnotation cleared _attachedAnnotation.

Common situations: Removing the last highlight while the layout is mid-pass; constructing components manually and inserting them into an adorner layer without attaching an annotation first; races between layout and annotation removal on background threads.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/MarkedHighlightComponent.cs:187

        #endregion Public Properties

        #region Public Methods

        /// <summary>
        /// There is no common transformation that can be used for all the children.
        /// Here we adjust the individual rendering transformation of each child and
        /// return the input transfor as a result
        /// </summary>
        /// <param name="transform">Transform to the AnnotatedElement.</param>
        /// <returns>Transform to the annotation component</returns>
        public GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            //we need to recalculate RenderingTransformations of the markers
            //according to their current positions in the TextView
            //after the content reflow
            if (_attachedAnnotation == null)
                throw new InvalidOperationException(SR.InvalidAttachedAnnotation);

            HighlightAnchor.GetDesiredTransform(transform);

            return transform;
        }

        /// <summary>
        /// Add an attached annotation to the component. The attached anchor will be used to add
        /// a highlight to the appropriate TextContainer
        /// </summary>
        /// <param name="attachedAnnotation">The attached annotation to be added to the component</param>
        public void AddAttachedAnnotation(IAttachedAnnotation attachedAnnotation)
        {
            if (_attachedAnnotation != null)
            {
                throw new ArgumentException(SR.MoreThanOneAttachedAnnotation);
            }

View on GitHub (pinned to 81131a70a4)