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
- Verify the component was added to this same context before removing; track added components in a set and only remove members.
- Guard the removal: only call RemoveFromHost when component.PresentationContext equals this context.
- Catch InvalidOperationException and treat it as already-removed if removal is idempotent by design.
- 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
- Track added components in a set and remove only members
- Route all add/remove through one context per layer
- Avoid double teardown paths (unload handler + explicit remove)
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
- SR.AnnotationServiceAlreadyExists
- SR.AnnotationServiceIsAlreadyEnabled
- SR.AnnotationServiceNotEnabled
- SR.Format(SR.ComponentAlreadyInPresentationContext…
- SR.InvalidAttachedAnnotation
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)