dotnet/orleans · error · ArgumentException
Provider type {providerType} must implement IDocumentIdProvi
Error message
Provider type {providerType} must implement IDocumentIdProvider or IPartitionKeyProvider. What it means
Thrown by HostingExtensions when registering a provider type for document ID or partition key resolution, but the type implements neither IDocumentIdProvider nor IPartitionKeyProvider. The code checks IPartitionKeyProvider.IsAssignableFrom(providerType); if false, it throws ArgumentException naming both required interfaces.
Source
Thrown at src/Azure/Orleans.Persistence.Cosmos/HostingExtensions.cs:295
if (typeof(IDocumentIdProvider).IsAssignableFrom(providerType))
{
services.AddKeyedSingleton(typeof(IDocumentIdProvider), name, providerType);
return;
}
#pragma warning disable CS0618 // Type or member is obsolete
if (typeof(IPartitionKeyProvider).IsAssignableFrom(providerType))
{
services.AddKeyedSingleton(typeof(IPartitionKeyProvider), name, providerType);
if (registerUnkeyedPartitionProvider)
{
services.TryAddSingleton(typeof(IPartitionKeyProvider), providerType);
}
return;
}
throw new ArgumentException(
$"Provider type {providerType} must implement {nameof(IDocumentIdProvider)} or {nameof(IPartitionKeyProvider)}.",
nameof(providerType));
#pragma warning restore CS0618 // Type or member is obsolete
}
}View on GitHub (pinned to fca799fa70)
Solutions
- Ensure the provider class implements IDocumentIdProvider (or the obsolete IPartitionKeyProvider), e.g., class MyProvider : IDocumentIdProvider { ... }.
- Verify the correct type is passed to the hosting extension — not the grain type, not the options type.
- Check that the Orleans.Persistence.Cosmos package is referenced so the interface is available.
- If migrating from IPartitionKeyProvider (obsolete), switch to IDocumentIdProvider.
Example fix
// before: missing interface
public class MyPartitionKeyProvider
{
public string GetPartitionKey(GrainId grainId) => grainId.ToString();
}
// after: implement the interface
public class MyPartitionKeyProvider : IDocumentIdProvider
{
public DocumentId GetDocumentId(GrainId grainId) => new(grainId.ToString(), grainId.ToString());
} Defensive patterns
Strategy: type-guard
Validate before calling
// Verify before registration
var providerType = typeof(MyProvider);
if (!typeof(IDocumentIdProvider).IsAssignableFrom(providerType)
&& !typeof(IPartitionKeyProvider).IsAssignableFrom(providerType))
throw new InvalidOperationException($"{providerType.Name} must implement IDocumentIdProvider or IPartitionKeyProvider."); Type guard
static bool IsValidProviderType(Type t) =>
typeof(IDocumentIdProvider).IsAssignableFrom(t) || typeof(IPartitionKeyProvider).IsAssignableFrom(t); Try / catch
try { siloBuilder.AddPartitionKeyProvider(name, providerType); }
catch (ArgumentException ex) when (ex.Message.Contains("must implement"))
{
logger.LogError(ex, "Provider type does not implement IDocumentIdProvider or IPartitionKeyProvider.");
throw;
} Prevention
- Always implement IDocumentIdProvider (or the obsolete IPartitionKeyProvider) on provider classes.
- Use a compile-time check or unit test to verify provider types implement the required interface.
- Migrate from IPartitionKeyProvider to IDocumentIdProvider when upgrading.
- Double-check the type passed to the hosting extension — pass the provider, not the grain.
When it happens
Trigger: Calling a hosting extension (e.g., AddPartitionKeyProvider or AddDocumentIdProvider) with a Type that does not implement either required interface. The extension checks assignability before registering and throws if neither interface is satisfied.
Common situations: Developer creates a class intended to be a partition key provider but forgets to implement IPartitionKeyProvider or IDocumentIdProvider. Renaming an interface during a refactor. Passing the wrong type by mistake (e.g., the grain class instead of the provider class). Version mismatch where the interface moved to a different namespace.
Related errors
- Custom document id or partition key providers are not compat
- Connection string '{connectionName}' was not found.
- Orleans:AdvertisedIPAddress must contain the Container Apps
- {key} must be a valid TCP port.
- graintype, siloNameFilter, and upperbound must be specified
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/7f4ce6a94773f232.
Report an issue: GitHub.