dotnet/wpf · error · InvalidOperationException
SR.AnnotationServiceIsAlreadyEnabled
Error message
SR.AnnotationServiceIsAlreadyEnabled
What it means
AnnotationService.Enable throws InvalidOperationException when Enable is called on a service instance that is already enabled (_isEnabled is true). Each AnnotationService can be enabled exactly once until Disable is called; re-enabling the live instance is an invalid state transition. This follows VerifyAccess, so it only occurs on the dispatcher thread.
Solutions
- Check service.IsEnabled before calling Enable and skip if already true.
- Call service.Disable() before re-enabling with a different store.
- Guard initialization with a flag so overlapping Loaded/navigation events cannot enable twice.
- Create a fresh AnnotationService instance (disabling the old one first) if a new store is required.
Example fix
// before
service.Enable(store); // may run again on re-Load
// after
if (!service.IsEnabled)
service.Enable(store); Defensive patterns
Strategy: validation
Validate before calling
if (!service.IsEnabled)
service.Enable(store); Type guard
bool CanEnable(AnnotationService s) => s != null && !s.IsEnabled;
Try / catch
try { service.Enable(store); }
catch (InvalidOperationException) { /* already enabled — no-op */ } Prevention
- Guard all Enable calls with an IsEnabled check.
- Initialize the service once in a single lifecycle hook, not in Loaded and navigation handlers both.
- Always pair Enable with Disable in teardown to allow clean re-enabling.
- Use an idempotent EnsureEnabled() wrapper around Enable.
When it happens
Trigger: Calling service.Enable(store) twice on the same AnnotationService instance without an intervening Disable(), e.g. Enable invoked from both a Loaded event and a navigation handler, or re-Enable after the viewer re-loads while the service stayed enabled.
Common situations: Double initialization from overlapping UI events (Loaded firing multiple times, tab re-activation); application startup code running twice; forgetting that Enable on a new store requires Disable first; MVVM re-attach logic enabling an already-enabled service.
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
- SR.AnnotationServiceAlreadyExists
- SR.AnnotationServiceNotEnabled
- SR.Format(SR.ComponentAlreadyInPresentationContext…
- SR.Format(SR.ComponentNotInPresentationContext, component)
- SR.InvalidAttachedAnnotation
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/a94d089e28382f27.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Annotations/AnnotationService.cs:165
#region Public Methods
/// <summary>
/// Enables the service with the given store.
/// </summary>
/// <param name="annotationStore">store to use for retreiving and persisting annotations</param>
/// <exception cref="ArgumentNullException">store is null</exception>
/// <exception cref="InvalidOperationException">DocumentViewerBase has content which is neither
/// FlowDocument or FixedDocument; only those two are supported</exception>
/// <exception cref="InvalidOperationException">this service or another service is already
/// enabled for the DocumentViewerBase</exception>
public void Enable(AnnotationStore annotationStore)
{
ArgumentNullException.ThrowIfNull(annotationStore);
VerifyAccess();
if (_isEnabled)
throw new InvalidOperationException(SR.AnnotationServiceIsAlreadyEnabled);
// Make sure there isn't a service above or below us
VerifyServiceConfiguration(_root);
// Post a background work item to load existing annotations. Do this early in the
// Enable method in case any later code causes an indirect call to LoadAnnotations,
// this cached operation will make that LoadAnnotations call a no-op.
_asyncLoadOperation = _root.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(LoadAnnotationsAsync), this);
// Enable the store and set it on the tree
_isEnabled = true;
_root.SetValue(AnnotationService.ServiceProperty, this);
_store = annotationStore;
// If our root is a DocumentViewerBase we need to setup some special processors.
DocumentViewerBase viewer = _root as DocumentViewerBase;
if (viewer != null)
{View on GitHub (pinned to 81131a70a4)