dotnet/wpf · error · ObjectDisposedException
SR.ObjectDisposed_StoreClosed
Error message
SR.ObjectDisposed_StoreClosed
What it means
XmlStreamStore throws an ObjectDisposedException with resource key SR.ObjectDisposed_StoreClosed when CheckStatus() detects the annotation store has already been disposed (IsDisposed == true). The store is unusable after Dispose(); any annotation operation on it is invalid. This guards against operating on a closed backing stream.
Solutions
- Check store.IsDisposed before every operation and recreate the store from the stream if needed
- Ensure Dispose is only called after all annotation work (including Flush) is complete
- Restructure so the store lives inside a using block that scopes all annotation operations
- Catch ObjectDisposedException and re-open the store on the same stream
Example fix
// before
store.Dispose();
store.Flush(); // throws ObjectDisposedException
// after
if (!store.IsDisposed)
{
store.Flush();
}
store.Dispose(); Defensive patterns
Strategy: try-catch
Validate before calling
if (store.IsDisposed) { store = RecreateStore(); }
if (!store.IsDisposed) store.Flush(); Type guard
bool Usable(XmlStreamStore s) => s != null && !s.IsDisposed;
Try / catch
try { store.Flush(); }
catch (ObjectDisposedException) { store = RecreateStore(); } Prevention
- Scope the store in a using block containing all annotation operations
- Never cache the store beyond its disposal point; resolve it via a factory
- Check IsDisposed before every call in long-lived code paths
When it happens
Trigger: Calling AddAnnotation, DeleteAnnotation, GetAnnotation, Flush, FindAnnotationIds, or InternalGetAnnotations after calling Dispose() on the XmlStreamStore instance.
Common situations: Disposing a store in a finally/using block and then calling Flush again; storing the store in a long-lived field while disposing it on window close but a background save still references it; double-dispose followed by retry logic that re-invokes store methods.
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.AnnotationServiceNotEnabled
- anchorLocator.Parts
- annotation component
- CurrentFixedPageWriter uninitialized
- FixedPageReader
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/42272925e81ef934.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Annotations/Storage/XmlStreamStore.cs:930
XPathNodeIterator iterator = tempNavigator.Select($@"//{AnnotationXmlConstants.Prefixes.CoreSchemaPrefix}:Annotation[@Id=""{XmlConvert.ToString(id)}""]", _namespaceManager);
if (iterator.MoveNext())
{
navigator = (XPathNavigator)iterator.Current;
}
}
return navigator;
}
/// <summary>
/// Verifies the store is in a valid state. Throws exceptions otherwise.
/// </summary>
private void CheckStatus()
{
lock (SyncRoot)
{
if (IsDisposed)
throw new ObjectDisposedException(null, SR.ObjectDisposed_StoreClosed);
if (_stream == null)
throw new InvalidOperationException(SR.StreamNotSet);
}
}
/// <summary>
/// Called from flush to serialize all annotations in the map
/// notice that delete takes care of the delete action both in the map
/// and in the store
/// </summary>
private void SerializeAnnotations()
{
List<Annotation> mapAnnotations = _storeAnnotationsMap.FindDirtyAnnotations();
foreach (Annotation annotation in mapAnnotations)
{
XPathNavigator editor = GetAnnotationNodeForId(annotation.Id);
if (editor == null)View on GitHub (pinned to 81131a70a4)