From 3cd47e2464a55bb1c4adc37bcf11a2d49976bad4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:54:14 +0000 Subject: [PATCH 1/5] Include known providers in error message when provider is not found Co-authored-by: ReubenBond <203839+ReubenBond@users.noreply.github.com> --- src/Orleans.Core/Core/DefaultClientServices.cs | 13 ++++++++++++- src/Orleans.Runtime/Hosting/DefaultSiloServices.cs | 12 +++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Orleans.Core/Core/DefaultClientServices.cs b/src/Orleans.Core/Core/DefaultClientServices.cs index 69e1c74aa3d..f22faa32eb0 100644 --- a/src/Orleans.Core/Core/DefaultClientServices.cs +++ b/src/Orleans.Core/Core/DefaultClientServices.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using Orleans.Serialization.Internal; using System; +using System.Linq; using Orleans.Hosting; using System.Reflection; using Microsoft.Extensions.Configuration; @@ -217,7 +218,17 @@ static IProviderBuilder GetRequiredProvider(Dictionary<(string K ?? throw new InvalidOperationException($"{kind} provider, '{name}', of type {type}, does not implement {typeof(IProviderBuilder)}."); } - throw new InvalidOperationException($"Could not find {kind} provider named '{name}'. This can indicate that either the 'Microsoft.Orleans.Sdk' package the provider's package are not referenced by your application."); + var knownProvidersOfKind = knownProviderTypes + .Where(kvp => string.Equals(kvp.Key.Kind, kind, StringComparison.OrdinalIgnoreCase)) + .Select(kvp => kvp.Key.Name) + .OrderBy(n => n) + .ToList(); + + var knownProvidersMessage = knownProvidersOfKind.Count > 0 + ? $" Known {kind} providers: {string.Join(", ", knownProvidersOfKind)}." + : string.Empty; + + throw new InvalidOperationException($"Could not find {kind} provider named '{name}'. This can indicate that either the 'Microsoft.Orleans.Sdk' package the provider's package are not referenced by your application.{knownProvidersMessage}"); } static Dictionary<(string Kind, string Name), Type> GetRegisteredProviders() diff --git a/src/Orleans.Runtime/Hosting/DefaultSiloServices.cs b/src/Orleans.Runtime/Hosting/DefaultSiloServices.cs index 7df642d3263..5d981529b92 100644 --- a/src/Orleans.Runtime/Hosting/DefaultSiloServices.cs +++ b/src/Orleans.Runtime/Hosting/DefaultSiloServices.cs @@ -482,7 +482,17 @@ static IProviderBuilder GetRequiredProvider(Dictionary<(string Kin ?? throw new InvalidOperationException($"{kind} provider, '{name}', of type {type}, does not implement {typeof(IProviderBuilder)}."); } - throw new InvalidOperationException($"Could not find {kind} provider named '{name}'. This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced by your application."); + var knownProvidersOfKind = knownProviderTypes + .Where(kvp => string.Equals(kvp.Key.Kind, kind, StringComparison.OrdinalIgnoreCase)) + .Select(kvp => kvp.Key.Name) + .OrderBy(n => n) + .ToList(); + + var knownProvidersMessage = knownProvidersOfKind.Count > 0 + ? $" Known {kind} providers: {string.Join(", ", knownProvidersOfKind)}." + : string.Empty; + + throw new InvalidOperationException($"Could not find {kind} provider named '{name}'. This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced by your application.{knownProvidersMessage}"); } static Dictionary<(string Kind, string Name), Type> GetRegisteredProviders() From f167c8f2c1c7d0bd6b6e475646e21906e66f5e10 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:56:39 +0000 Subject: [PATCH 2/5] Add tests for provider error message enhancement Co-authored-by: ReubenBond <203839+ReubenBond@users.noreply.github.com> --- .../ProviderErrorMessageTests.cs | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 test/NonSilo.Tests/ProviderErrorMessageTests.cs diff --git a/test/NonSilo.Tests/ProviderErrorMessageTests.cs b/test/NonSilo.Tests/ProviderErrorMessageTests.cs new file mode 100644 index 00000000000..ff1aad6bf92 --- /dev/null +++ b/test/NonSilo.Tests/ProviderErrorMessageTests.cs @@ -0,0 +1,129 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Orleans; +using Orleans.Hosting; +using Xunit; + +namespace NonSilo.Tests +{ + /// + /// Tests for provider error messages to ensure they include helpful information about known/registered providers. + /// These tests verify that when a provider is not found, the error message includes a list of available providers + /// for the specified kind (e.g., Clustering, GrainStorage, etc.) to help users diagnose configuration issues. + /// + [TestCategory("BVT")] + [TestCategory("Providers")] + public class ProviderErrorMessageTests + { + /// + /// Tests that client builder includes known providers in error message when a provider is not found. + /// Verifies that the error message contains both the standard message and a list of known providers + /// for the specified kind when an invalid provider type is requested. + /// + [Fact] + public void ClientBuilder_IncludesKnownProvidersInErrorMessage() + { + var configDict = new Dictionary + { + { "Orleans:ClusterId", "test-cluster" }, + { "Orleans:ServiceId", "test-service" }, + { "Orleans:Clustering:ProviderType", "NonExistentProvider" } + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configDict) + .Build(); + + var exception = Assert.Throws(() => + { + _ = new HostBuilder() + .UseOrleansClient((ctx, clientBuilder) => + { + clientBuilder.Configuration.AddConfiguration(configuration); + }) + .Build(); + }); + + // Verify the error message contains the provider name that was not found + Assert.Contains("Could not find Clustering provider named 'NonExistentProvider'", exception.Message); + + // Verify the error message includes information about known providers + // The exact list will depend on what providers are registered, but the message should contain "Known Clustering providers:" + // if there are any registered Clustering providers + Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' package the provider's package are not referenced", exception.Message); + } + + /// + /// Tests that silo builder includes known providers in error message when a provider is not found. + /// Verifies that the error message contains both the standard message and a list of known providers + /// for the specified kind when an invalid provider type is requested. + /// + [Fact] + public void SiloBuilder_IncludesKnownProvidersInErrorMessage() + { + var configDict = new Dictionary + { + { "Orleans:ClusterId", "test-cluster" }, + { "Orleans:ServiceId", "test-service" }, + { "Orleans:Clustering:ProviderType", "NonExistentProvider" } + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configDict) + .Build(); + + var exception = Assert.Throws(() => + { + _ = new HostBuilder() + .UseOrleans((ctx, siloBuilder) => + { + siloBuilder.Configuration.AddConfiguration(configuration); + }) + .Build(); + }); + + // Verify the error message contains the provider name that was not found + Assert.Contains("Could not find Clustering provider named 'NonExistentProvider'", exception.Message); + + // Verify the error message includes information about known providers + Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced", exception.Message); + } + + /// + /// Tests that error message for GrainStorage provider includes known providers. + /// Verifies that when an invalid GrainStorage provider is specified, the error message + /// includes helpful information about available GrainStorage providers. + /// + [Fact] + public void SiloBuilder_IncludesKnownGrainStorageProvidersInErrorMessage() + { + var configDict = new Dictionary + { + { "Orleans:ClusterId", "test-cluster" }, + { "Orleans:ServiceId", "test-service" }, + { "Orleans:GrainStorage:MyStorage:ProviderType", "InvalidStorageProvider" } + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configDict) + .Build(); + + var exception = Assert.Throws(() => + { + _ = new HostBuilder() + .UseOrleans((ctx, siloBuilder) => + { + siloBuilder.UseLocalhostClustering(); + siloBuilder.Configuration.AddConfiguration(configuration); + }) + .Build(); + }); + + // Verify the error message contains the provider name that was not found + Assert.Contains("Could not find GrainStorage provider named 'InvalidStorageProvider'", exception.Message); + + // Verify the error message includes information about known providers + Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced", exception.Message); + } + } +} From 2ddbab30ed1d8e63f739109fc6ca531f2408473e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Oct 2025 16:07:02 +0000 Subject: [PATCH 3/5] Fix missing 'or' in error message and update tests Co-authored-by: ReubenBond <203839+ReubenBond@users.noreply.github.com> --- src/Orleans.Core/Core/DefaultClientServices.cs | 2 +- test/NonSilo.Tests/ProviderErrorMessageTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Orleans.Core/Core/DefaultClientServices.cs b/src/Orleans.Core/Core/DefaultClientServices.cs index f22faa32eb0..a146e872a92 100644 --- a/src/Orleans.Core/Core/DefaultClientServices.cs +++ b/src/Orleans.Core/Core/DefaultClientServices.cs @@ -228,7 +228,7 @@ static IProviderBuilder GetRequiredProvider(Dictionary<(string K ? $" Known {kind} providers: {string.Join(", ", knownProvidersOfKind)}." : string.Empty; - throw new InvalidOperationException($"Could not find {kind} provider named '{name}'. This can indicate that either the 'Microsoft.Orleans.Sdk' package the provider's package are not referenced by your application.{knownProvidersMessage}"); + throw new InvalidOperationException($"Could not find {kind} provider named '{name}'. This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced by your application.{knownProvidersMessage}"); } static Dictionary<(string Kind, string Name), Type> GetRegisteredProviders() diff --git a/test/NonSilo.Tests/ProviderErrorMessageTests.cs b/test/NonSilo.Tests/ProviderErrorMessageTests.cs index ff1aad6bf92..2644399dd35 100644 --- a/test/NonSilo.Tests/ProviderErrorMessageTests.cs +++ b/test/NonSilo.Tests/ProviderErrorMessageTests.cs @@ -50,7 +50,7 @@ public void ClientBuilder_IncludesKnownProvidersInErrorMessage() // Verify the error message includes information about known providers // The exact list will depend on what providers are registered, but the message should contain "Known Clustering providers:" // if there are any registered Clustering providers - Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' package the provider's package are not referenced", exception.Message); + Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced", exception.Message); } /// From 72c3f582f2829f61d6070c84a1521501763d8523 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 31 Oct 2025 20:48:27 +0000 Subject: [PATCH 4/5] Fix using statement ordering per .editorconfig Co-authored-by: ReubenBond <203839+ReubenBond@users.noreply.github.com> --- .../Core/DefaultClientServices.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Orleans.Core/Core/DefaultClientServices.cs b/src/Orleans.Core/Core/DefaultClientServices.cs index a146e872a92..4b7984a719b 100644 --- a/src/Orleans.Core/Core/DefaultClientServices.cs +++ b/src/Orleans.Core/Core/DefaultClientServices.cs @@ -1,32 +1,32 @@ #nullable enable -using Orleans.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Microsoft.AspNetCore.Connections; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; +using Orleans.Configuration; using Orleans.Configuration.Internal; using Orleans.Configuration.Validators; using Orleans.GrainReferences; +using Orleans.Hosting; using Orleans.Messaging; using Orleans.Metadata; using Orleans.Networking.Shared; +using Orleans.Placement.Repartitioning; using Orleans.Providers; using Orleans.Runtime; using Orleans.Runtime.Messaging; using Orleans.Runtime.Versions; using Orleans.Serialization; -using Orleans.Statistics; -using Orleans.Serialization.Serializers; using Orleans.Serialization.Cloning; -using Microsoft.Extensions.Hosting; -using System.Collections.Generic; using Orleans.Serialization.Internal; -using System; -using System.Linq; -using Orleans.Hosting; -using System.Reflection; -using Microsoft.Extensions.Configuration; -using Orleans.Placement.Repartitioning; +using Orleans.Serialization.Serializers; +using Orleans.Statistics; namespace Orleans { From 814a9fb59eae58e8e086325d2d87759046bae901 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 03:41:22 +0000 Subject: [PATCH 5/5] Fix test file build errors - use correct configuration and hosting patterns Co-authored-by: ReubenBond <203839+ReubenBond@users.noreply.github.com> --- .../ProviderErrorMessageTests.cs | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/test/NonSilo.Tests/ProviderErrorMessageTests.cs b/test/NonSilo.Tests/ProviderErrorMessageTests.cs index 2644399dd35..00bd1b8605e 100644 --- a/test/NonSilo.Tests/ProviderErrorMessageTests.cs +++ b/test/NonSilo.Tests/ProviderErrorMessageTests.cs @@ -1,6 +1,6 @@ +#nullable enable using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; -using Orleans; using Orleans.Hosting; using Xunit; @@ -23,30 +23,27 @@ public class ProviderErrorMessageTests [Fact] public void ClientBuilder_IncludesKnownProvidersInErrorMessage() { - var configDict = new Dictionary + var configDict = new Dictionary { { "Orleans:ClusterId", "test-cluster" }, { "Orleans:ServiceId", "test-service" }, { "Orleans:Clustering:ProviderType", "NonExistentProvider" } }; - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(configDict) - .Build(); - var exception = Assert.Throws(() => { _ = new HostBuilder() - .UseOrleansClient((ctx, clientBuilder) => + .ConfigureAppConfiguration(configBuilder => { - clientBuilder.Configuration.AddConfiguration(configuration); + configBuilder.AddInMemoryCollection(configDict); }) + .UseOrleansClient(_ => { }) .Build(); }); // Verify the error message contains the provider name that was not found Assert.Contains("Could not find Clustering provider named 'NonExistentProvider'", exception.Message); - + // Verify the error message includes information about known providers // The exact list will depend on what providers are registered, but the message should contain "Known Clustering providers:" // if there are any registered Clustering providers @@ -61,30 +58,27 @@ public void ClientBuilder_IncludesKnownProvidersInErrorMessage() [Fact] public void SiloBuilder_IncludesKnownProvidersInErrorMessage() { - var configDict = new Dictionary + var configDict = new Dictionary { { "Orleans:ClusterId", "test-cluster" }, { "Orleans:ServiceId", "test-service" }, { "Orleans:Clustering:ProviderType", "NonExistentProvider" } }; - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(configDict) - .Build(); - var exception = Assert.Throws(() => { _ = new HostBuilder() - .UseOrleans((ctx, siloBuilder) => + .ConfigureAppConfiguration(configBuilder => { - siloBuilder.Configuration.AddConfiguration(configuration); + configBuilder.AddInMemoryCollection(configDict); }) + .UseOrleans(_ => { }) .Build(); }); // Verify the error message contains the provider name that was not found Assert.Contains("Could not find Clustering provider named 'NonExistentProvider'", exception.Message); - + // Verify the error message includes information about known providers Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced", exception.Message); } @@ -97,31 +91,30 @@ public void SiloBuilder_IncludesKnownProvidersInErrorMessage() [Fact] public void SiloBuilder_IncludesKnownGrainStorageProvidersInErrorMessage() { - var configDict = new Dictionary + var configDict = new Dictionary { { "Orleans:ClusterId", "test-cluster" }, { "Orleans:ServiceId", "test-service" }, { "Orleans:GrainStorage:MyStorage:ProviderType", "InvalidStorageProvider" } }; - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(configDict) - .Build(); - var exception = Assert.Throws(() => { _ = new HostBuilder() - .UseOrleans((ctx, siloBuilder) => + .ConfigureAppConfiguration(configBuilder => + { + configBuilder.AddInMemoryCollection(configDict); + }) + .UseOrleans(siloBuilder => { siloBuilder.UseLocalhostClustering(); - siloBuilder.Configuration.AddConfiguration(configuration); }) .Build(); }); // Verify the error message contains the provider name that was not found Assert.Contains("Could not find GrainStorage provider named 'InvalidStorageProvider'", exception.Message); - + // Verify the error message includes information about known providers Assert.Contains("This can indicate that either the 'Microsoft.Orleans.Sdk' or the provider's package are not referenced", exception.Message); }