{"record":{"id":"71c79201c1aece67","repo":"microsoft/aspire","slug":"state-has-not-been-loaded","errorCode":null,"errorMessage":"State has not been loaded.","messagePattern":"State has not been loaded\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Pipelines/Internal/DeploymentStateManagerBase.cs","lineNumber":294,"sourceCode":"        {\n            // Remove the section from the state by passing null\n            SetNestedPropertyValue(_state, section.SectionName, null);\n            await SaveStateToStorageAsync(_state, section.SectionName, section.OriginalData, cancellationToken).ConfigureAwait(false);\n            section.OriginalData = [];\n        }\n        finally\n        {\n            _stateLock.Release();\n        }\n    }\n\n    private async Task EnsureStateAndSectionAsync(DeploymentStateSection section, CancellationToken cancellationToken)\n    {\n        await LoadStateAsync(cancellationToken).ConfigureAwait(false);\n\n        if (_state is null)\n        {\n            throw new InvalidOperationException(\"State has not been loaded.\");\n        }\n\n        // Atomically check version and update using lock + Dictionary\n        lock (_sectionsLock)\n        {\n            if (_sections.TryGetValue(section.SectionName, out var metadata))\n            {\n                if (metadata.Version != section.Version)\n                {\n                    throw new InvalidOperationException(\n                        $\"Concurrency conflict detected in section '{section.SectionName}'. \" +\n                        $\"Expected version {section.Version}, but current version is {metadata.Version}. \" +\n                        $\"This typically indicates the section was modified after it was acquired. \" +\n                        $\"Ensure the section is saved before being modified by another operation.\");\n                }\n            }\n\n            // Create new metadata with incremented version","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Pipelines/Internal/DeploymentStateManagerBase.cs#L276-L312","documentation":"EnsureStateAndSectionAsync calls LoadStateAsync and then verifies the in-memory _state was actually populated before allowing SaveSectionAsync or DeleteSectionAsync to proceed. If the state remains null after the load attempt, the manager cannot safely mutate a section, so it throws InvalidOperationException.","triggerScenarios":"Calling SaveSectionAsync or DeleteSectionAsync when no deployment state has been loaded — e.g. no state file exists and the load path left _state null, or the manager was constructed without a valid state source.","commonSituations":"Saving a section in a fresh environment before any state file was created; a custom/derived state manager that overrides loading and leaves _state unset; calling section APIs outside the normal pipeline lifecycle where LoadStateAsync was expected to run.","solutions":["Ensure the state is initialized (LoadStateAsync completes successfully and creates/loads the state file) before saving or deleting sections.","On first deployment, let the pipeline bootstrap state instead of calling section APIs cold.","If using a custom state manager, make sure your load path assigns _state before section operations."],"exampleFix":"// before\nawait manager.SaveSectionAsync(section, ...); // state never loaded\n// after\nawait manager.LoadStateAsync(ct);\nawait manager.SaveSectionAsync(section, ...);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await manager.SaveSectionAsync(section, ct); }\ncatch (InvalidOperationException ex) when (ex.Message == \"State has not been loaded.\")\n{\n    await manager.LoadStateAsync(ct);\n    await manager.SaveSectionAsync(section, ct);\n}","preventionTips":["Always call LoadStateAsync (or go through the pipeline lifecycle) before section operations.","Don't construct section-saving calls outside the normal deploy/publish flow on a cold manager.","In custom managers, ensure every load path assigns the in-memory state."],"tags":["state","lifecycle","initialization"],"backgroundTag":"invalid-state-transition","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}