{"record":{"id":"339b324e1a7fab89","repo":"dotnet/orleans","slug":"the-transactional-state-storage-provider-name-is-r","errorCode":null,"errorMessage":"The transactional state storage provider name is required.","messagePattern":"The transactional state storage provider name is required\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/AWS/Orleans.Transactions.DynamoDB/Hosting/DynamoDBTransactionServiceCollectionExtensions.cs","lineNumber":32,"sourceCode":"/// <summary>\n/// <see cref=\"IServiceCollection\"/> extensions.\n/// </summary>\npublic static class DynamoDBTransactionServiceCollectionExtensions\n{\n    internal static IServiceCollection AddDynamoDBTransactionalStateStorage(this IServiceCollection services,\n        string name,\n        Action<OptionsBuilder<DynamoDBTransactionalStorageOptions>>? configureOptions = null)\n    {\n        configureOptions?.Invoke(services.AddOptions<DynamoDBTransactionalStorageOptions>(name));\n        services.AddTransient<IConfigurationValidator>(sp => new DynamoDBTransactionalStorageOptionsValidator(sp.GetRequiredService<IOptionsMonitor<DynamoDBTransactionalStorageOptions>>().Get(name), name));\n        services.ConfigureNamedOptionForLogging<DynamoDBTransactionalStorageOptions>(name);\n        services.AddTransient<IPostConfigureOptions<DynamoDBTransactionalStorageOptions>, DefaultStorageProviderSerializerOptionsConfigurator<DynamoDBTransactionalStorageOptions>>();\n\n        services.TryAddSingleton<ITransactionalStateStorageFactory>(sp => sp.GetRequiredKeyedService<ITransactionalStateStorageFactory>(ProviderConstants.DEFAULT_STORAGE_PROVIDER_NAME));\n        services.AddKeyedSingleton<ITransactionalStateStorageFactory>(name, (sp, key) =>\n            DynamoDBTransactionalStateStorageFactory.Create(\n                sp,\n                key as string ?? throw new InvalidOperationException(\"The transactional state storage provider name is required.\")));\n        services.AddSingleton<ILifecycleParticipant<ISiloLifecycle>>(s => (ILifecycleParticipant<ISiloLifecycle>)s.GetRequiredKeyedService<ITransactionalStateStorageFactory>(name));\n\n        return services;\n    }\n}\n","sourceCodeStart":14,"sourceCodeEnd":38,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/AWS/Orleans.Transactions.DynamoDB/Hosting/DynamoDBTransactionServiceCollectionExtensions.cs#L14-L38","documentation":"Thrown inside the keyed-singleton factory registered by AddDynamoDBTransactionalStateStorage when the DI service key is not a string. Orleans registers transactional state storage by provider name (a string); resolving ITransactionalStateStorageFactory with a non-string key means the registration was misused or the keyed-service lookup bypassed the documented API.","triggerScenarios":"Manually resolving ITransactionalStateStorageFactory via GetRequiredKeyedService with a non-string key (e.g., an enum, int, or Type), or a custom hosting extension that registers the factory under a non-string key.","commonSituations":"Custom DI wiring that uses non-string keyed services; experimental code resolving the factory directly; .NET 8+ keyed DI used with a non-string key by mistake.","solutions":["Always register and resolve the factory by a string provider name (the default API path).","Use AddDynamoDBTransactionalStateStorage(name, ...) and resolve with the same string name.","If you need a non-string key, wrap it: register under key.ToString() and document the mapping.","Audit custom hosting extensions for non-string keyed registrations of this factory."],"exampleFix":"// before\nsp.GetRequiredKeyedService<ITransactionalStateStorageFactory>(42); // non-string key -> throws\n\n// after\nsp.GetRequiredKeyedService<ITransactionalStateStorageFactory>(\"myTxStore\");","handlingStrategy":"validation","validationCode":"string name = key as string ?? throw new InvalidOperationException(\"Provider name must be a string.\");\nvar factory = sp.GetRequiredKeyedService<ITransactionalStateStorageFactory>(name);","typeGuard":"static bool IsStringKey(object? key) => key is string s && !string.IsNullOrWhiteSpace(s);","tryCatchPattern":"try { var f = sp.GetRequiredKeyedService<ITransactionalStateStorageFactory>(name); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"provider name is required\"))\n{\n    logger.LogCritical(\"Resolved transactional storage factory with a non-string key.\");\n    throw;\n}","preventionTips":["Always register and resolve the factory by a string provider name.","Avoid non-string keyed services for Orleans storage factories.","Wrap non-string keys via .ToString() with documented mapping."],"tags":["aws","dynamodb","transactions","dependency-injection","orleans"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}