microsoft/aspire · error · InvalidOperationException

State has not been loaded.

Error message

State has not been loaded.

What it means

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.

Solutions

  1. Ensure the state is initialized (LoadStateAsync completes successfully and creates/loads the state file) before saving or deleting sections.
  2. On first deployment, let the pipeline bootstrap state instead of calling section APIs cold.
  3. If using a custom state manager, make sure your load path assigns _state before section operations.

Example fix

// before
await manager.SaveSectionAsync(section, ...); // state never loaded
// after
await manager.LoadStateAsync(ct);
await manager.SaveSectionAsync(section, ...);
Defensive patterns

Strategy: try-catch

Try / catch

try { await manager.SaveSectionAsync(section, ct); }
catch (InvalidOperationException ex) when (ex.Message == "State has not been loaded.")
{
    await manager.LoadStateAsync(ct);
    await manager.SaveSectionAsync(section, ct);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/71c79201c1aece67. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/Pipelines/Internal/DeploymentStateManagerBase.cs:294

        {
            // Remove the section from the state by passing null
            SetNestedPropertyValue(_state, section.SectionName, null);
            await SaveStateToStorageAsync(_state, section.SectionName, section.OriginalData, cancellationToken).ConfigureAwait(false);
            section.OriginalData = [];
        }
        finally
        {
            _stateLock.Release();
        }
    }

    private async Task EnsureStateAndSectionAsync(DeploymentStateSection section, CancellationToken cancellationToken)
    {
        await LoadStateAsync(cancellationToken).ConfigureAwait(false);

        if (_state is null)
        {
            throw new InvalidOperationException("State has not been loaded.");
        }

        // Atomically check version and update using lock + Dictionary
        lock (_sectionsLock)
        {
            if (_sections.TryGetValue(section.SectionName, out var metadata))
            {
                if (metadata.Version != section.Version)
                {
                    throw new InvalidOperationException(
                        $"Concurrency conflict detected in section '{section.SectionName}'. " +
                        $"Expected version {section.Version}, but current version is {metadata.Version}. " +
                        $"This typically indicates the section was modified after it was acquired. " +
                        $"Ensure the section is saved before being modified by another operation.");
                }
            }

            // Create new metadata with incremented version

View on GitHub (pinned to 25830f84bd)