{"record":{"id":"92e3524e9db19cd8","repo":"dotnet/orleans","slug":"azuretablejournalstorageprovider-has-not-been-init","errorCode":null,"errorMessage":"AzureTableJournalStorageProvider has not been initialized. Ensure the silo lifecycle has started before using journal storage.","messagePattern":"AzureTableJournalStorageProvider has not been initialized\\. Ensure the silo lifecycle has started before using journal storage\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorage.cs","lineNumber":1319,"sourceCode":"\n        public string? JournalFormatKey { get; }\n\n        public TableClientProvider TableClientProvider { get; }\n\n        public AzureTableJournalStorageInstruments Instruments { get; }\n    }\n\n    internal abstract class TableClientProvider\n    {\n        public abstract TableClient GetTableClient();\n    }\n\n    internal sealed class InitializedTableClientProvider : TableClientProvider\n    {\n        private TableClient? _tableClient;\n\n        public override TableClient GetTableClient()\n            => _tableClient ?? throw new InvalidOperationException(\n                $\"{nameof(AzureTableJournalStorageProvider)} has not been initialized. Ensure the silo lifecycle has started before using journal storage.\");\n\n        public void SetTableClient(TableClient tableClient)\n        {\n            ArgumentNullException.ThrowIfNull(tableClient);\n            _tableClient = tableClient;\n        }\n    }\n}\n","sourceCodeStart":1301,"sourceCodeEnd":1329,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorage.cs#L1301-L1329","documentation":"The default InitializedTableClientProvider.GetTableClient (AzureTableJournalStorage.cs:1318) was called before SetTableClient had supplied a TableClient. The TableClient is assigned during silo lifecycle initialization; using journal storage before that phase completes throws this InvalidOperationException. It signals a lifecycle ordering bug, not a data problem.","triggerScenarios":"Any journal read/write issued before the AzureTableJournalStorageProvider's lifecycle OnActive has run and called SetTableClient; e.g., a grain or startup service that touches a journal during an earlier lifecycle stage.","commonSituations":"A hosted service or grain attempts journal access during Configure or earlier lifecycle phases; a test instantiates the storage and calls methods without driving the lifecycle; misordered DI such that a consumer resolves and uses the storage before the provider is initialized.","solutions":["Defer journal access until after the silo/client has fully started (the storage's lifecycle OnActive has completed).","In tests, call SetTableClient with a real or mock TableClient before exercising the storage.","Ensure the consuming component participates in a lifecycle stage later than the storage provider."],"exampleFix":"// before — journal used during early startup\npublic MyStartupService(JournalStorage s) { s.Read(...); }\n\n// after — wait until lifecycle active\npublic Task OnActive(CancellationToken ct) { /* journal safe here */ }","handlingStrategy":"validation","validationCode":"// Ensure the provider is initialized before first use\ntry { _ = storageShared.TableClientProvider.GetTableClient(); }\ncatch (InvalidOperationException) { /* not yet initialized — defer use */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Touch journal storage only after the silo/client has fully started.","In tests, call SetTableClient before exercising the storage.","Order consumers in a later lifecycle stage than the storage provider."],"tags":["lifecycle","configuration","table-client"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}