Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BatchFixAllProvider crashes with "An element with the same key but a different value already exists" #57660

Open
jnm2 opened this issue Nov 9, 2021 · 7 comments
Assignees
Labels
Area-IDE Bug Tenet-Reliability Customer telemetry indicates that the product is failing in a crash/hang/dataloss manner.
Milestone

Comments

@jnm2
Copy link
Contributor

jnm2 commented Nov 9, 2021

Version Used: 17.0.0

Got this after trying to invoking "remove unnecessary usings" for a whole solution after adding global usings. VS froze for a while, then showed this (it opened at this position and didn't move at all) and remained frozen for a long time:

image

Then the gold bar appeared saying that BatchFixAllProvider encountered an error:

System.ArgumentException : An element with the same key but a different value already exists. Key: '(DocumentId, #bc308e8d-b194-f1c4-c02d-910f2e9fa704 - SomeTestClass.TestContainer.g.cs)'
   at System.Collections.Immutable.ImmutableSortedDictionary`2.FillFromEmpty(IEnumerable`1 items,Boolean overwriteOnCollision)
   at System.Collections.Immutable.ImmutableSortedDictionary`2.AddRange(IEnumerable`1 items,Boolean overwriteOnCollision,Boolean avoidToSortedMap)
   at System.Collections.Immutable.ImmutableSortedDictionary.ToImmutableSortedDictionary[TSource,TKey,TValue](IEnumerable`1 source,Func`2 keySelector,Func`2 elementSelector,IComparer`1 keyComparer)
   at Microsoft.CodeAnalysis.TextDocumentStates`1..ctor(IEnumerable`1 states)
   at async Microsoft.CodeAnalysis.SolutionState.CompilationTracker.FinalizeCompilationAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.SolutionState.CompilationTracker.BuildCompilationInfoFromScratchAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.SolutionState.CompilationTracker.BuildCompilationInfoAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.SolutionState.CompilationTracker.GetOrBuildCompilationInfoAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.SolutionState.CompilationTracker.GetCompilationSlowAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Diagnostics.AnalyzerHelper.CreateCompilationWithAnalyzersAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Diagnostics.EngineV2.DiagnosticIncrementalAnalyzer.IdeLatestDiagnosticGetter.AppendDiagnosticsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Diagnostics.EngineV2.DiagnosticIncrementalAnalyzer.DiagnosticGetter.GetDiagnosticsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.CodeFixService.GetProjectDiagnosticsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.FixAllContext.GetFilteredDiagnosticsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.FixAllContext.GetProjectDiagnosticsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.FixAllContext.DiagnosticProvider.<GetDocumentDiagnosticsToFixAsync>g__GetDocumentDiagnosticsToFixWorkerAsync|3_1(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.FixAllContext.DiagnosticProvider.GetDocumentDiagnosticsToFixAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.BatchFixAllProvider.DetermineDiagnosticsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.BatchFixAllProvider.FixSingleContextAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.BatchFixAllProvider.FixAllContextsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeFixes.DefaultFixAllProviderHelpers.GetFixAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.FixAllGetFixesService.GetFixAllCodeActionAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.FixAllGetFixesService.GetFixAllOperationsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeActions.CodeAction.GetOperationsCoreAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Roslyn.Utilities.TaskExtensions.WaitAndGetResult_CanCallOnBackground[T](Task`1 task,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedAction.InvokeWorker(Func`1 getFromDocument,IProgressTracker progressTracker,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Extensions.IExtensionManagerExtensions.PerformAction(IExtensionManager extensionManager,Object extension,Action action)

Restarting VS unblocked this operation.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Nov 9, 2021
@jinujoseph jinujoseph added Bug Tenet-Reliability Customer telemetry indicates that the product is failing in a crash/hang/dataloss manner. and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Nov 11, 2021
@jinujoseph jinujoseph added this to the 17.1 milestone Nov 11, 2021
@mavasani
Copy link
Contributor

mavasani commented Nov 18, 2021

We are crashing here:

var generatedDocuments = new TextDocumentStates<SourceGeneratedDocumentState>(generatedDocumentsBuilder.ToImmutableAndClear());

generatedDocumentsBuilder seems to have multiple source generated document states with the same ID. I am not sure if the correct fix here is to be resilient to this in TextDocumentStates constructor or this needs to be handled in FinalizeCompilationAsync. Moving to @jasonmalinowski.

@mavasani mavasani assigned jasonmalinowski and unassigned mavasani Nov 18, 2021
@jasonmalinowski
Copy link
Member

jasonmalinowski commented Jan 13, 2022

Hmm, @jnm2 do you know what type of project this was? I know we had some bugs if we got the same generator added twice, but not sure if this would manifest here precisely. I'd assume that if that was happening this wouldn't have worked after restart though...

@jasonmalinowski
Copy link
Member

So I'm not able to reproduce by a naive test, but look at telemetry it does appear there's a number of hits with this same stack, including 17.1 too so it's not something we've fixed yet. I've opened https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1463535 as an internal bug which links up with our telemetry systems so we can get more info on it.

@jasonmalinowski
Copy link
Member

We did get a telemetry report with an attached crash dump. The GeneratorDriver's list of generators has a duplicate generator; we have two instances of MvvmGen.SourceGenerators's MvvmGen.ViewModelGenerator loaded and added to the GeneratorDriver at once. Oddly, it appears to be two separate instances of the same generator object, i.e. .GetType() on the two generators will give the same result and are loaded from the same assembly. That seems hard to have happen, as AnalyzerFileReference tries to cache the same object; my hunch is we must have removed and readded a reference and there's a bug where the first removal didn't work (due to some sort of mismatch with the object identities), and a later re-addition added a second copy.

In any case, this doesn't appear to be a duplicate of #56619 which I was hoping it might be, or at least at the point of the fault we no longer have a duplicate in the main Project.AnalyzerReferences list.

@jnm2: when you said you added global usings, do you recall if you did that by editing a source file, or editing the project file? I recognize I'm asking you to remember a subtle detail from months ago, but if you think it was a project file edit that'd make sense.

@jasonmalinowski jasonmalinowski modified the milestones: 17.1, 17.1.P3, 17.2 Mar 17, 2022
@jasonmalinowski
Copy link
Member

The crash was in our OOP process which also makes me think it could have been fallout from #58990, but we're still seeing hits for 17.2 so that doesn't explain everything.

@jnm2
Copy link
Contributor Author

jnm2 commented Mar 17, 2022

@jasonmalinowski It for sure was by editing the project file. It's easy to remember because I haven't written a global using in a source file ever.

@jinujoseph jinujoseph modified the milestones: 17.2, 17.3 May 5, 2022
@jasonmalinowski jasonmalinowski modified the milestones: 17.3, 17.4 Aug 26, 2022
jasonmalinowski added a commit to jasonmalinowski/roslyn that referenced this issue Oct 14, 2022
We've seen a few places in the wild where a customer ends up with
a generator installed twice into their project. This was causing an
issue with how we generate DocumentIds for generated documents:
we compute that as a stable hash over some pieces of information so
that way we geneate consistent IDs in different processes, and
a generated file that disappears due to an edit and comes back can also
have the same ID.

The hashing algorithm for a DocumentId included the generator's type
name and the generator's assembly name, but if you have two generators
with the same assembly name we'd collide. This could happen if you
have two different generators with the same name, or your project file
is messed up and causing a generator to be added from two different
paths at once. This latter case isn't a scenario we support, but this
change at least ensures Roslyn won't be throwing exceptions which
ends up requiring investigation.

Related to dotnet#56619, but doesn't
entirely close it, a duplicate generator producing duplicate files
will still be confusing. This may also address
dotnet#57660 but the belief is there's
a race condition there too, as the dumps I've seen don't show duplicate
references in the project.
@jasonmalinowski
Copy link
Member

jasonmalinowski commented Oct 27, 2022

This should be fixed by #65039.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE Bug Tenet-Reliability Customer telemetry indicates that the product is failing in a crash/hang/dataloss manner.
Projects
None yet
Development

No branches or pull requests

5 participants