dotnet/wpf · error · ArgumentException
SR.AnnotationAlreadyExists
Error message
SR.AnnotationAlreadyExists
What it means
XmlStreamStore.AddAnnotation rejects annotations whose Id already exists in the store, throwing ArgumentException(SR.AnnotationAlreadyExists, nameof(newAnnotation)). Annotation Ids are unique keys within the store, so adding a duplicate would corrupt the store's invariants.
Solutions
- Check GetAnnotations() or the annotation's existence before adding, and skip or update instead of adding duplicates.
- Generate a fresh unique Id (Guid) when re-adding a copied annotation.
- For updates to an existing annotation, use the appropriate update/modify API rather than AddAnnotation.
Example fix
// before
store.AddAnnotation(loadedAnnotation); // throws if Id already stored
// after
if (store.GetAnnotations(new Guid(loadedAnnotation.Id.ToString())).FirstOrDefault() == null)
store.AddAnnotation(loadedAnnotation);
else
loadedAnnotation = new Annotation(Guid.NewGuid(), loadedAnnotation.Cargos); // new Id for the copy Defensive patterns
Strategy: validation
Validate before calling
bool exists = store.GetAnnotations().Cast<Annotation>().Any(a => a.Id == newAnnotation.Id); if (!exists) store.AddAnnotation(newAnnotation);
Try / catch
try { store.AddAnnotation(newAnnotation); }
catch (ArgumentException ex) when (ex.Message.Contains("already exists")) { /* treat as duplicate: update or skip */ } Prevention
- Regenerate Ids (new Guid) when cloning or copying annotations.
- Make import routines idempotent by checking existence before adding.
- Use one code path for add-vs-update instead of re-adding loaded annotations.
When it happens
Trigger: Calling store.AddAnnotation(annotation) with an annotation whose Id matches one already persisted (or already present in the in-memory store map), e.g. re-adding a loaded annotation or cloning one without regenerating its Id.
Common situations: Re-running an import routine without clearing the store; copying annotation objects (clone/copy constructors preserve Id); deserializing the same annotation twice into one store.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- InvalidEnumArgumentException("action", (int)action…
- InvalidEnumArgumentException("action", (int)action…
- SR.Format(SR.XmlNodeAlreadyOwned, "change", "change")
- SR.IncorrectLocatorPartType
- SR.MoreThanOneAttachedAnnotation
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/544771e4dabb49af.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Annotations/Storage/XmlStreamStore.cs:134
public override void AddAnnotation(Annotation newAnnotation)
{
ArgumentNullException.ThrowIfNull(newAnnotation);
// We are going to modify internal data. Lock the object
// to avoid modifications from other threads
lock (SyncRoot)
{
//fire trace event
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnnotation, EventTrace.Event.AddAnnotationBegin);
try
{
CheckStatus();
XPathNavigator editor = GetAnnotationNodeForId(newAnnotation.Id);
// we are making sure that the newAnnotation doesn't already exist in the store
if (editor != null)
throw new ArgumentException(SR.AnnotationAlreadyExists, nameof(newAnnotation));
// we are making sure that the newAnnotation doesn't already exist in the store map
if (_storeAnnotationsMap.FindAnnotation(newAnnotation.Id) != null)
throw new ArgumentException(SR.AnnotationAlreadyExists, nameof(newAnnotation));
// simply add the annotation to the map to save on performance
// notice that we need to tell the map that this instance of the annotation is dirty
_storeAnnotationsMap.AddAnnotation(newAnnotation, true);
}
finally
{
//fire trace event
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnnotation, EventTrace.Event.AddAnnotationEnd);
}
}
OnStoreContentChanged(new StoreContentChangedEventArgs(StoreContentAction.Added, newAnnotation));
}View on GitHub (pinned to 81131a70a4)