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

Feature 'Razor TagHelperProvider Feature' is currently unavailable due to an internal error. #11532

Open
Peter-Juhasz opened this issue Feb 21, 2025 · 10 comments
Assignees

Comments

@Peter-Juhasz
Copy link

VS 17.14 P1

Added an existing project to a blank solution and got this error: "Feature 'Razor TagHelperProvider Feature' is currently unavailable due to an internal error."

StreamJsonRpc.RemoteInvocationException: Method not found: 'Void Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext.set_ExcludeHidden(Boolean)'.
   at StreamJsonRpc.JsonRpc.<InvokeCoreAsync>d__156`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.CodeAnalysis.Remote.BrokeredServiceConnection`1.<TryInvokeAsync>d__18`1.MoveNext()
RPC server exception:
System.MissingMethodException: Method not found: 'Void Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext.set_ExcludeHidden(Boolean)'.
      at Microsoft.CodeAnalysis.ProjectExtensions.GetTagHelpersAsync(Project project, RazorProjectEngine projectEngine, ITelemetryReporter telemetryReporter, CancellationToken cancellationToken)
      at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
      at Microsoft.CodeAnalysis.ProjectExtensions.GetTagHelpersAsync(Project project, RazorProjectEngine projectEngine, ITelemetryReporter telemetryReporter, CancellationToken cancellationToken)
      at Microsoft.CodeAnalysis.Remote.Razor.RemoteTagHelperResolver.GetTagHelpersAsync(Project workspaceProject, RazorConfiguration configuration, CancellationToken cancellationToken)
      at Microsoft.CodeAnalysis.Remote.Razor.RemoteTagHelperProviderService.GetTagHelpersDeltaCoreAsync(Solution solution, ProjectSnapshotHandle projectHandle, Int32 lastResultId, CancellationToken cancellationToken)
      at Microsoft.CodeAnalysis.Remote.RemoteWorkspace.<>c__DisplayClass7_0`1.<<RunWithSolutionAsync>g__ProcessSolutionAsync|1>d.MoveNext()
   --- End of stack trace from previous location ---
      at Microsoft.CodeAnalysis.Remote.RemoteWorkspace.RunWithSolutionAsync[T](AssetProvider assetProvider, Checksum solutionChecksum, Boolean updatePrimaryBranch, Func`2 implementation, CancellationToken cancellationToken)
      at Microsoft.CodeAnalysis.Remote.RemoteWorkspace.RunWithSolutionAsync[T](AssetProvider assetProvider, Checksum solutionChecksum, Boolean updatePrimaryBranch, Func`2 implementation, CancellationToken cancellationToken)
      at Microsoft.CodeAnalysis.Remote.RemoteWorkspaceManager.RunServiceAsync[T](ServiceBrokerClient client, Checksum solutionChecksum, Func`2 implementation, CancellationToken cancellationToken)
@DustinCampbell
Copy link
Member

Thaanks very much for the report and the stack trace. cc @phil-allen-msft and @davidwengier: This looks to be the same issue as https://developercommunity.visualstudio.com/t/Error-displayed-for-feature-on-project-o/10848099, which almost certainly caused by having two IsExternalInit types in the mix as modreqs.

@DustinCampbell
Copy link
Member

I've done a bit of investigation and am capturing that here.

I've looked at the Razor ServiceHub binaries that installed in VS Preview. These are located under $(VSRoot)\Common7\IDE\CommonExtensions\Microsoft\RazorLanguageServices\ServiceHubCore.

Here are some important details:

  1. All Razor binaries are compiled for .NET Core 8.0, which is definitely what we want.
  2. There are three binaries compiled for .NETStandard2.0: Microsoft.VisualStudio.LanguageService.Protocol, Microsoft.VisualStudio.LanguageService.Protocol.Extensions, and Microsoft.VisualStudio.LanguageService.Protocol.Internal. I'm not sure if these are strictly needed in Roslyn OOP, but that's unclear at the moment. I doubt very much that any of these would contribute to the issue, since none of them provide IVT access to any of the Razor binaries.
  3. In the call stack above, there are two methods in conflict:
    • Void Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext.set_ExcludeHidden(Boolean), which is defined in Microsft.CodeAnalysis.Razor.Compiler.dll. (code)
    • Microsoft.CodeAnalysis.ProjectExtensions.GetTagHelpersAsync(Project project, RazorProjectEngine projectEngine, ITelemetryReporter telemetryReporter, CancellationToken cancellationToken), which is defined in Microsoft.AspNetCore.Razor.ProjectEngineHost.dll. (code)
  4. Both assemblies, MS.CA.Razor.Compiler.dll and MS.ANC.Razor.ProjectEngineHost.dll are compiled for .NET Core 8.0 and neither contains a private copy of IsExternalInit.cs.
  5. At the IL level, both methods use IsExternalInit from System.Runtime:
    • Void Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext.set_ExcludeHidden(Boolean)
      .property instance bool ExcludeHidden()
      {
          .get instance bool Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext::get_ExcludeHidden()
          .set instance void modreq ([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext::set_ExcludeHidden(bool)
      }
      
    • Microsoft.CodeAnalysis.ProjectExtensions.GetTagHelpersAsync(Project project, RazorProjectEngine projectEngine, ITelemetryReporter telemetryReporter, CancellationToken cancellationToken)
      IL_00f1: callvirt     instance void modreq ([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) [Microsoft.CodeAnalysis.Razor.Compiler]Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext::set_ExcludeHidden(bool)
      ...
      IL_00f8: callvirt     instance void modreq ([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) [Microsoft.CodeAnalysis.Razor.Compiler]Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext::set_IncludeDocumentation(bool)
      

So, everything looks to be in order from this initial investigation. Something fishy is going on. 🤔

@davidwengier
Copy link
Member

I don't have much context here, but I was asked about an IsExternalInit ngen failure yesterday, and it seems dotnet/roslyn#77186 was the fix. I think @333fred did the investigation. Related?

@DustinCampbell
Copy link
Member

DustinCampbell commented Feb 21, 2025

I've been wondering about the IsExternalInit that's present in MS.CA.ExternalAccess.Razor.dll and I think it's a red herring. The call stack above is a call from MS.ANC.Razor.ProjectEngineHost to an init-only setter in MS.Ca.Razor.Compiler.dll. Neither of those assemblies directly or transitively references MS.CA.ExternalAccess.Razor.dll, so I don't see how it could cause that call stack.

In addition, I would expect to see a LOT more reporting of this issue if it were widespread. That leads me to wonder if it's some sort of upgrade issue. Maybe one binary isn't being updated or something like that.

@DustinCampbell
Copy link
Member

WRT to ExternalAccess.Razor.dll, I wonder if it should be compiled it for .NET Core and .NET Framework rather than .NET Standard, or split into two projects. It definitely represents a layering violation by shipping bits that are client-side only and server-side only within the same assembly. And, the server-side assembly wouldn't have IsExternalInit if it were compiled to .NET Core.

@DustinCampbell
Copy link
Member

@davidwengier: Do we have any reports of this issue that include a dump? It should be possible to poke around a dump at the exception and see where the other IsExternalInit is coming from.

@davidwengier
Copy link
Member

davidwengier commented Feb 21, 2025

I think this is the first actual report I've seen of the issue. I saw mention of "IsExternalInit" fly past in an Infraswat chat message the other day, which is why I knew about the above PR, and I personally hit this at one point and avoided using a record as a result, but I don't think I've seen a customer report before. I think maybe there was an AzDo ticket that came up in triage once, but Phil tagged you and I don't have a link. Derp, nevermind, I'm thinking of the feedback ticket you linked above, which you tagged me on.

@davidwengier
Copy link
Member

WRT to ExternalAccess.Razor.dll, I wonder if it should be compiled it for .NET Core and .NET Framework rather than .NET Standard, or split into two projects

In my mind Andrew is effectively working on this, creating a new EA.Razor.Features, and my hope is that OOP can reference that instead of the existing one. It's not quite the same as splitting the existing EA, but hopefully the effect is similar.

@ryzngard
Copy link
Contributor

and my hope is that OOP can reference that instead of the existing one

Once I get the split done do we just need to move some of the stuff to it for referencing? Should be pretty easy since it will already be target net9 (what Roslyn LSP targets)

@davidwengier
Copy link
Member

Yeah, that would be my hope. Essentially Microsoft.CodeAnalyisis.Remote.Razor moves from MS.CA.EA.Razor to MS.CA.EA.Razor.Features, and we move stuff into the shared project until it all compiles. Shouldn't even need a dual insertion :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants