title: Blazor proj from scratch+nuget: "There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'"
body: <p><strong>[Final update 07.12.2020 23:50 --&gt; for everyone seeking for the anwser]</strong></p>
  <p>You are probably adding some nuget package which has in fields DEPENDENCIES .NET Core 3.1. For example Serilog.AspNetCore 3.4.0. In this very example you can include Serilog.AspNetCore 3.2.0 because it has in DEPENDENCIES only .NetStandard 2.0. See more explanation in @Ogglas answer.</p>
  <p>There is not enough space on earth to ask the one and only question: &quot;Why, o why Microsoft?&quot;:) The message is not clearly correlating issue with the solution - this is the lightest euphemism i am capable of making :)</p>
  <p>For me, Blazor is very promising but it is still more a beta version. And not only for me. The startblazoring guys are claiming, that Blazor can be fickle sometimes. And I cannot agree more;) I am keeping finger crossed for it. But I suppose it would be a &quot;ready product&quot; only after .NET 6.0.</p>
  <p><strong>[Original Topic]</strong></p>
  <p>This is so frustrating :)</p>
  <p>I hate errors, when I cannot simply interact and understood where it is coming from. I know, I am ignorant, and If I would pay more attention to &quot;how is the blazor app created&quot; I would understand in eye blink.</p>
  <p>But for now it is only frustrating. What is? The error message:</p>
  <blockquote>
  <p>Severity  Code    Description Project File    Line    Suppression State
  Error   NETSDK1082  There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'.    TestBlazorAppNoRuntimeError.Client  C:\Program Files\dotnet\sdk\5.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets   387</p>
  </blockquote>
  <p>Really, what can you fix here?:D Ehhhhh. I understand that .NET 5 is a &quot;new thing&quot;. I understand Blazor is a &quot;new thing&quot; But really? It is really easy to &quot;break&quot; ;) (with a message that is saying nothing)</p>
  <p>So what did I do?</p>
  <p>Did I create very complicated project with hundreds of thousands of files?</p>
  <p><strong>No</strong></p>
  <p>Did I add hundreds of thousands of nuget packages.</p>
  <p><strong>No</strong></p>
  <p>All it takes is to create Blazor Webassembly app and add one nuget package to the shared (common) library (FYI: IdentityServer4 package). That is all folks. Kudos if you would now, that this package specificly is causing this issue (because i found out only by mistake):</p>
  <blockquote>
  <p>There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'.</p>
  </blockquote>
  <p>Really, there is a great correlation here: between the error message and the package being added (this was sarcasm if anyone missed it:) )</p>
  <p>So if you want to reproduce it create create &quot;Blazor Webassembly&quot;:</p>
  <p><a href="https://i.stack.imgur.com/PRHBU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/PRHBU.png" alt="enter image description here" /></a></p>
  <p>I don't suppose the options chosen are making the difference. But if this is the case - you can see what option I did choose. Then just add IdentityServer4 nuget package to shared library:</p>
  <p><a href="https://www.nuget.org/packages/IdentityServer4/" rel="nofollow noreferrer">https://www.nuget.org/packages/IdentityServer4/</a></p>
  <p>That is all</p>
  <p>If you are too lazy - download this project and check for yourself:</p>
  <p><a href="https://ufile.io/751l5wgq" rel="nofollow noreferrer">https://ufile.io/751l5wgq</a></p>
  <p>I saw hundreds of SOF topics regarding this message:</p>
  <blockquote>
  <p>There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'.</p>
  </blockquote>
  <p>But none of those was so easy to reproduce.</p>
  <p>Why I am creating this topic?</p>
  <p>Because I did try to implement (by copy-pasting to my solution) what guys did create in Blazor boilerplate here:
  <a href="https://github.com/enkodellc/blazorboilerplate" rel="nofollow noreferrer">https://github.com/enkodellc/blazorboilerplate</a></p>
  <p>At the beginning, by mistake, I've added Identity4 NuGet instead of Identity4.storage and that is why I did observe such behavior (such error) and did correlate this package with this error. When I rolled back from Identity4 to Identity4.storage everything was correct once again. But after that I did a lot of code transfer from this repository. And once I've ended, right now, everything is compiling but once again I have:</p>
  <blockquote>
  <p>There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'.</p>
  </blockquote>
  <p>And it is driving me crazy. Maybe you would have some idea, how to find out WHAT is causing this error (exactly the same as previously Identity4 nuget package was causing it)</p>
  <p><strong>[UPDATE 06.12.2020 12:30]</strong></p>
  <p>The question here is more: &quot;Why is it happening and how to locate package causing the issue&quot; I know that I can second guess what is causing this message to appear.</p>
  <p>I did a little investigation. This error is showing in this target:</p>
    
  <p></p>
  <pre><code>&lt;ResolveRuntimePackAssets FrameworkReferences=&quot;@(FrameworkReference)&quot;
                            ResolvedRuntimePacks=&quot;@(ResolvedRuntimePack)&quot;
                            UnavailableRuntimePacks=&quot;@(UnavailableRuntimePack)&quot;
                            SatelliteResourceLanguages=&quot;$(SatelliteResourceLanguages)&quot;
                            DesignTimeBuild=&quot;$(DesignTimeBuild)&quot;&gt;
    &lt;Output TaskParameter=&quot;RuntimePackAssets&quot; ItemName=&quot;RuntimePackAsset&quot; /&gt;
  &lt;/ResolveRuntimePackAssets&gt;
  
  &lt;ItemGroup&gt;
    &lt;ReferenceCopyLocalPaths Include=&quot;@(RuntimePackAsset)&quot;
                             Condition=&quot;'$(CopyLocalLockFileAssemblies)' == 'true' and ('$(SelfContained)' == 'true' or '%(RuntimePackAsset.RuntimePackAlwaysCopyLocal)' == 'true')&quot; /&gt;
  &lt;/ItemGroup&gt;
  </code></pre>
    
  <p>so I did google ResolveRuntimePackAssets and found this repo and this file:</p>
  <p><a href="https://github.com/dotnet/sdk/blob/release/5.0.2xx/src/Tasks/Microsoft.NET.Build.Tasks/ResolveRuntimePackAssets.cs" rel="nofollow noreferrer">https://github.com/dotnet/sdk/blob/release/5.0.2xx/src/Tasks/Microsoft.NET.Build.Tasks/ResolveRuntimePackAssets.cs</a> and such code:</p>
  <pre><code>foreach (var unavailableRuntimePack in UnavailableRuntimePacks)
  {
      if (frameworkReferenceNames.Contains(unavailableRuntimePack.ItemSpec))
      {
          //  This is a runtime pack that should be used, but wasn't available for the specified RuntimeIdentifier
          //  NETSDK1082: There was no runtime pack for {0} available for the specified RuntimeIdentifier '{1}'.
          Log.LogError(Strings.NoRuntimePackAvailable, unavailableRuntimePack.ItemSpec,
              unavailableRuntimePack.GetMetadata(MetadataKeys.RuntimeIdentifier));
      }
  }
  </code></pre>
  <p>Looks like the code &quot;causing&quot; the issue (this calls for writing down information in message about: <code>unavailableRuntimePack.ItemSpec</code> - it would be so much easier;))</p>
  <p>So right now the only thing is to locate what is filling this: <code>UnavailableRuntimePacks</code> property. I don't see any code doing that so it have to be some reflection. I've located this code which is probably doing it:</p>
  <p><a href="https://github.com/dotnet/sdk/blob/release/5.0.2xx/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs" rel="nofollow noreferrer">https://github.com/dotnet/sdk/blob/release/5.0.2xx/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs</a></p>
  <p>And this method:</p>
  <pre><code>private void ProcessRuntimeIdentifier(
      string runtimeIdentifier,
      KnownRuntimePack selectedRuntimePack,
      string runtimePackVersion,
      List&lt;string&gt; additionalFrameworkReferencesForRuntimePack,
      HashSet&lt;string&gt; unrecognizedRuntimeIdentifiers,
      List&lt;ITaskItem&gt; unavailableRuntimePacks,
      List&lt;ITaskItem&gt; runtimePacks,
      List&lt;ITaskItem&gt; packagesToDownload,
      string isTrimmable,
      bool addToPackageDownload)
  {
      var runtimeGraph = new RuntimeGraphCache(this).GetRuntimeGraph(RuntimeGraphPath);
      var knownFrameworkReferenceRuntimePackRuntimeIdentifiers = selectedRuntimePack.RuntimePackRuntimeIdentifiers.Split(';');
  
      string runtimePackRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(
              runtimeGraph,
              runtimeIdentifier,
              knownFrameworkReferenceRuntimePackRuntimeIdentifiers,
              out bool wasInGraph);
  
      if (runtimePackRuntimeIdentifier == null)
      {
          if (wasInGraph)
          {
              //  Report this as an error later, if necessary.  This is because we try to download
              //  all available runtime packs in case there is a transitive reference to a shared
              //  framework we don't directly reference.  But we don't want to immediately error out
              //  here if a runtime pack that we might not need to reference isn't available for the
              //  targeted RID (e.g. Microsoft.WindowsDesktop.App for a linux RID).
              var unavailableRuntimePack = new TaskItem(selectedRuntimePack.Name);
              unavailableRuntimePack.SetMetadata(MetadataKeys.RuntimeIdentifier, runtimeIdentifier);
              unavailableRuntimePacks.Add(unavailableRuntimePack);
          }
          else if (!unrecognizedRuntimeIdentifiers.Contains(runtimeIdentifier))
          {
              //  NETSDK1083: The specified RuntimeIdentifier '{0}' is not recognized.
              Log.LogError(Strings.RuntimeIdentifierNotRecognized, runtimeIdentifier);
              unrecognizedRuntimeIdentifiers.Add(runtimeIdentifier);
          }
      }
      else if (addToPackageDownload)
      {
          foreach (var runtimePackNamePattern in selectedRuntimePack.RuntimePackNamePatterns.Split(';'))
          {
              string runtimePackName = runtimePackNamePattern.Replace(&quot;**RID**&quot;, runtimePackRuntimeIdentifier);
  
              if (runtimePacks != null)
              {
                  TaskItem runtimePackItem = new TaskItem(runtimePackName);
                  runtimePackItem.SetMetadata(MetadataKeys.NuGetPackageId, runtimePackName);
                  runtimePackItem.SetMetadata(MetadataKeys.NuGetPackageVersion, runtimePackVersion);
                  runtimePackItem.SetMetadata(MetadataKeys.FrameworkName, selectedRuntimePack.Name);
                  runtimePackItem.SetMetadata(MetadataKeys.RuntimeIdentifier, runtimePackRuntimeIdentifier);
                  runtimePackItem.SetMetadata(MetadataKeys.IsTrimmable, isTrimmable);
  
                  if (selectedRuntimePack.RuntimePackAlwaysCopyLocal)
                  {
                      runtimePackItem.SetMetadata(MetadataKeys.RuntimePackAlwaysCopyLocal, &quot;true&quot;);
                  }
  
                  if (additionalFrameworkReferencesForRuntimePack != null)
                  {
                      runtimePackItem.SetMetadata(MetadataKeys.AdditionalFrameworkReferences, string.Join(&quot;;&quot;, additionalFrameworkReferencesForRuntimePack));
                  }
  
                  runtimePacks.Add(runtimePackItem);
              }
  
              TaskItem packageToDownload = new TaskItem(runtimePackName);
              packageToDownload.SetMetadata(MetadataKeys.Version, runtimePackVersion);
  
              packagesToDownload.Add(packageToDownload);
          }
      }
  }
  </code></pre>
  <p>After analysing it, the reason why Identity4 (for example) is causing this issue is because runtimePackRuntimeIdentifier is null and wasInGraph was true :) But what does mean, we have to dig a little bit further. The key thing here is the method GetBestMatchingRid:</p>
  <pre><code>public static string GetBestMatchingRid(RuntimeGraph runtimeGraph, string runtimeIdentifier,
      IEnumerable&lt;string&gt; availableRuntimeIdentifiers, out bool wasInGraph)
  {
      wasInGraph = runtimeGraph.Runtimes.ContainsKey(runtimeIdentifier);
  
      HashSet&lt;string&gt; availableRids = new HashSet&lt;string&gt;(availableRuntimeIdentifiers);
      foreach (var candidateRuntimeIdentifier in runtimeGraph.ExpandRuntime(runtimeIdentifier))
      {
          if (availableRids.Contains(candidateRuntimeIdentifier))
          {
              return candidateRuntimeIdentifier;
          }
      }
  
      //  No compatible RID found in availableRuntimeIdentifiers
      return null;
  }
  </code></pre>
  <p>So here we see that <code>runtimePackRuntimeIdentifier</code> was null because it was not found on: <code>availableRuntimeIdentifiers</code>. And this variable is defined as:</p>
  <p><code>var knownFrameworkReferenceRuntimePackRuntimeIdentifiers = selectedRuntimePack.RuntimePackRuntimeIdentifiers.Split(';');</code></p>
  <p>So let's see how is it defined (in the code below variable <code>runtimePackForRuntimeIDProcessing</code> is <code>selectedRuntimePack</code> from the above mention)</p>
  <pre><code>KnownRuntimePack runtimePackForRuntimeIDProcessing;
  if (knownFrameworkReference.Name.Equals(knownFrameworkReference.RuntimeFrameworkName, StringComparison.OrdinalIgnoreCase))
  {
      //  Only add runtime packs where the framework reference name matches the RuntimeFrameworkName
      //  Framework references for &quot;profiles&quot; will use the runtime pack from the corresponding non-profile framework
      runtimePackForRuntimeIDProcessing = selectedRuntimePack.Value;
      includeInPackageDownload = true;
  }
  else if (!knownFrameworkReference.RuntimePackRuntimeIdentifiers.Equals(selectedRuntimePack?.RuntimePackRuntimeIdentifiers))
  {
      // If the profile has a different set of runtime identifiers than the runtime pack, use the profile.
      runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack();
      includeInPackageDownload = true;
  }
  else
  {
      // For the remaining profiles, don't include them in package download but add them to unavaliable if necessary.
      runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack();
      includeInPackageDownload = false;
  }
  </code></pre>
  <p>But this is as far as I can go. I don't understand without further investigation how this <code>selectedRuntimePack.RuntimePackRuntimeIdentifiers</code> should be defined. This is the key thing here. Clearly for some reasons IdentityServer4 doesn't belong to <code>selectedRuntimePack.RuntimePackRuntimeIdentifiers</code> and this is the answer I am looking for :)</p>