Sunday, January 05, 2020

The specified ITextSnapshot doesn't belong to the correct TextBuffer - a solution

I'm assuming you're reading this because you encountered this error message in a Visual Studio log and didn't know what to do about it.

"The specified ITextSnapshot doesn't belong to the correct TextBuffer."

You may even have found a number of other blog and forum posts looking for answers but finding none.
I've been there myself.

This is a record of how I fixed this issue. This applies to how I addressed it in an extension I'm writing. If you're just using VS and not writing an extension yourself this is unlikely to be useful or interesting. If you are investigating this because of an extension you're writing, please note that you might be having this issue because of another issue to me.

Disclaimer over, I noticed this error occurring when a config file was deleted from the project.

The call stack in the log wasn't immediately helpful either.

System.ArgumentException: The specified ITextSnapshot doesn't belong to the correct TextBuffer.
   at Microsoft.VisualStudio.Text.SnapshotSpan.TranslateTo(ITextSnapshot targetSnapshot, SpanTrackingMode spanTrackingMode)
   at Microsoft.VisualStudio.Text.Tagging.Implementation.TagAggregator`1.<GetTagsForBuffer>d__47.MoveNext()
   at Microsoft.VisualStudio.Text.Tagging.Implementation.TagAggregator`1.<InternalGetTags>d__51.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at Microsoft.VisualStudio.Text.AdornmentLibrary.Squiggles.Implementation.SquiggleVisualManager.GetNormalizedSquiggleSpanCollections(ITextViewLine line)
   at Microsoft.VisualStudio.Text.AdornmentLibrary.Squiggles.Implementation.SquiggleVisualManager.UpdateVisualsOn(IEnumerable`1 lines, Boolean removeOldSquiggles)
   at Microsoft.VisualStudio.Text.AdornmentLibrary.Squiggles.Implementation.SquiggleVisualManager.UpdateSquigglesOnInvalidatedSpans()
   at Microsoft.VisualStudio.Text.AdornmentLibrary.Squiggles.Implementation.SquiggleVisualManager.OnLayoutChanged(Object sender, TextViewLayoutChangedEventArgs e)
   at Microsoft.VisualStudio.Text.Utilities.GuardedOperations.RaiseEvent[TArgs](Object sender, EventHandler`1 eventHandlers, TArgs args)

However, on reflection, it did provide a hint.
The mention of `GetTagsForBuffer` made me look at what I was doing with tagging.

In my `ITagger<T>` implementation I was using a cache of created tags to avoid needing to recreate them unnecessarily. However, it seems that changing the project that an open file is in causes a new TextBuffer to be created.
The consequence of this is that my cached tags now refer to a Snapshot with a different TextBuffer and that causes VS to have (but log) an exception.

My solution is that in the GetTags method, I check that the TextBuffer of the NormalizedSnapshotSpanCollection matches the TextBuffer of the SnapShot of the cached tags.
I only return the tags if they do match and if they don't I invalidate the cache for that file.

Hopefully, this helps save someone else some time trying to debug a similar issue.


Post a Comment