dotnet/orleans · critical · OrleansConfigurationException

Custom document id or partition key providers are not compat

Error message

Custom document id or partition key providers are not compatible with partition key path set to /GrainType

What it means

Thrown during Cosmos container initialization when the partition key path is /GrainType (GRAINTYPE_PARTITION_KEY_PATH) but a custom document ID or partition key provider is registered. The /GrainType partition strategy is an Orleans-managed scheme that expects the DefaultDocumentIdProvider without a custom partition key provider. Mixing the two is explicitly forbidden because it would produce inconsistent partition key assignments.

Source

Thrown at src/Azure/Orleans.Persistence.Cosmos/CosmosGrainStorage.cs:333

            foreach (var idx in _options.StateFieldsToIndex)
            {
                var path = idx.StartsWith("/") ? idx[1..] : idx;
                stateContainer.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = $"/\"State\"/\"{path}\"/?" });
            }
        }

        const int maxRetries = 3;
        for (var retry = 0; retry <= maxRetries; ++retry)
        {
            var containerResponse = await db.CreateContainerIfNotExistsAsync(stateContainer, _options.ContainerThroughputProperties);

            if (containerResponse.StatusCode == HttpStatusCode.OK || containerResponse.StatusCode == HttpStatusCode.Created)
            {
                var container = containerResponse.Resource;
                _partitionKeyPath = container.PartitionKeyPath;
                if (_partitionKeyPath == GRAINTYPE_PARTITION_KEY_PATH &&
                    (_documentIdProvider is not DefaultDocumentIdProvider defaultProvider || defaultProvider.HasCustomPartitionKeyProvider))
                    throw new OrleansConfigurationException("Custom document id or partition key providers are not compatible with partition key path set to /GrainType");
            }

            if (retry == maxRetries || dbResponse.StatusCode != HttpStatusCode.Created || containerResponse.StatusCode == HttpStatusCode.Created)
            {
                break;  // Apparently some throttling logic returns HttpStatusCode.OK (not 429) when the collection wasn't created in a new DB.
            }
            await Task.Delay(1000);
        }
    }

    private async Task TryDeleteDatabase()
    {
        try
        {
            await _client.GetDatabase(_options.DatabaseName).DeleteAsync().ConfigureAwait(false);
        }
        catch (CosmosException dce) when (dce.StatusCode == HttpStatusCode.NotFound)
        {

View on GitHub (pinned to fca799fa70)

Solutions

  1. Choose one partition strategy: either use /GrainType path (remove custom IPartitionKeyProvider/IDocumentIdProvider registrations) or use a custom provider (change the container partition key path to something else like /PartitionKey).
  2. If you need custom partition keys, do not set the container's partition key path to /GrainType.
  3. Remove the ConfigurePartitionKeyProvider call if using the /GrainType default strategy.
  4. Delete and recreate the Cosmos container with the correct partition key path for the chosen strategy.

Example fix

// before: conflicting configuration
siloBuilder.AddCosmosGrainStorage("store", o =>
{
    // container has /GrainType partition key
});
siloBuilder.Services.AddSingleton<IPartitionKeyProvider, MyPartitionKeyProvider>();

// after: pick one strategy
siloBuilder.AddCosmosGrainStorage("store", o =>
{
    o.PartitionKeyPath = "/PartitionKey"; // custom provider strategy
});
Defensive patterns

Strategy: validation

Validate before calling

// At startup, verify partition key path and provider strategy are compatible
var partitionKeyPath = configuration["Orleans:Persistence:store:PartitionKeyPath"];
var hasCustomProvider = sp.GetService<IPartitionKeyProvider>() is not null
    || sp.GetKeyedService<IDocumentIdProvider>("store") is not DefaultDocumentIdProvider;
if (partitionKeyPath == "/GrainType" && hasCustomProvider)
    throw new InvalidOperationException("Cannot use /GrainType partition with a custom ID/partition provider.");

Try / catch

try { await host.StartAsync(ct); }
catch (OrleansConfigurationException ex) when (ex.Message.Contains("not compatible with partition key path"))
{
    logger.LogCritical(ex, "Cosmos partition key path /GrainType conflicts with custom provider — choose one strategy.");
    throw;
}

Prevention

When it happens

Trigger: Cosmos container was created or found with PartitionKeyPath="/GrainType", and _documentIdProvider is not a DefaultDocumentIdProvider (or it is, but HasCustomPartitionKeyProvider is true — meaning an IPartitionKeyProvider was injected). This combination is detected during the Init lifecycle stage after CreateContainerIfNotExistsAsync.

Common situations: Developer configures UseCosmosGrainStorageWithGrainTypePartitionKeyPath (or sets the container partition key to /GrainType) but also calls ConfigurePartitionKeyProvider or AddPartitionKeyProvider to register a custom IPartitionKeyProvider. Mixing two partitioning strategies. Copy-paste config from one provider to another.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/71a9d4757f6a4f21. Report an issue: GitHub.