dotnet/wpf · error · InvalidOperationException

SR.Format(SR.ComponentNotInPresentationContext, component)

Error message

SR.Format(SR.ComponentNotInPresentationContext, component)

What it means

RemoveFromHost throws this InvalidOperationException when asked to remove an annotation component that is not hosted by this AdornerPresentationContext: FindAnnotationAdorner cannot locate a matching AnnotationAdorner in the adorner layer. The framework only removes components it can find, so an unknown component indicates caller bookkeeping is out of sync with the actual visual tree.

Solutions

  1. Verify the component was added to this same context before removing; track added components in a set and only remove members.
  2. Guard the removal: only call RemoveFromHost when component.PresentationContext equals this context.
  3. Catch InvalidOperationException and treat it as already-removed if removal is idempotent by design.
  4. Re-add the component if it was unintentionally removed, then remove it properly in a single teardown path.

Example fix

// before
context.RemoveFromHost(component); // throws if not present
// after
if (component.PresentationContext == context)
    context.RemoveFromHost(component);
Defensive patterns

Strategy: validation

Validate before calling

bool canRemove = component.PresentationContext is AdornerPresentationContext ctx && ReferenceEquals(ctx, thisContext);
if (canRemove) thisContext.RemoveFromHost(component);

Type guard

bool IsHostedHere(IAnnotationComponent c, AdornerPresentationContext ctx) => ReferenceEquals(c?.PresentationContext, ctx);

Try / catch

try { context.RemoveFromHost(component); }
catch (InvalidOperationException) { /* already removed; treat as idempotent */ }

Prevention

When it happens

Trigger: Calling AdornerPresentationContext.RemoveFromHost(component) with a component that was never added to this context, was already removed, or was removed via a different AdornerLayer so no matching AnnotationAdorner exists in the layer.

Common situations: Double-removal after an unload/unload-then-remove sequence; removing a component against the wrong AdornerLayer (e.g. after the element moved to a different viewer); keeping stale references to components after their DocumentViewer/AdornerDecorator was rebuilt.

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/1f3814daa4c7faca. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/AdornerPresentationContext.cs:194

        /// </summary>
        /// <param name="component">Component to remove from host</param>
        /// <param name="reorder">if true - recalculate z-order</param>
        public override void RemoveFromHost(IAnnotationComponent component, bool reorder)
        {
            ArgumentNullException.ThrowIfNull(component);

            if (IsInternalComponent(component))
            {
                _annotationAdorner.AnnotationComponent.PresentationContext = null;
                _adornerLayer.Remove(_annotationAdorner);
                _annotationAdorner.RemoveChildren();
                _annotationAdorner = null;
            }
            else
            {// need to find annotation adorner in layer, remove it and do house-keeping
                AnnotationAdorner foundAdorner = this.FindAnnotationAdorner(component);

                if (foundAdorner == null) throw new InvalidOperationException(SR.Format(SR.ComponentNotInPresentationContext, component));

                _adornerLayer.Remove(foundAdorner);
                foundAdorner.RemoveChildren();

                // now get rid of reference from presentation context of annotation component to annotation adorner
                AdornerPresentationContext p = component.PresentationContext as AdornerPresentationContext;

                p?.ResetInternalAnnotationAdorner();

                // finally get rid of reference from annotation component to presentation context
                component.PresentationContext = null;
            }
        }

        /// <summary>
        /// Invalidate the transform for this adorner. called when adorner inside changed aspects of the transform.
        /// This might go away if InvalidateMeasure works 
        /// (unclear if Peter means this should work on the adorner or even one down on the annotation component itself)

View on GitHub (pinned to 81131a70a4)