microsoft/aspire · error · InvalidOperationException

The Azure sandbox group deployment scope changed while…

Error message

The Azure sandbox group deployment scope changed while sandbox deployment state still exists. Run 'aspire destroy' with the previous sandbox group configuration before deploying to the new scope.

What it means

Sandbox deployment state records the subscription, resource group, region, and sandbox group under which it was created. If any of these differ from the current deployment scope while state still exists, deploying would operate on the wrong sandbox, so an InvalidOperationException demands an 'aspire destroy' with the previous configuration first.

Solutions

  1. Run 'aspire destroy' with the previous sandbox group configuration to clear state, then deploy with the new scope
  2. Manually delete the sandbox deployment state (and the Azure resources) if destroy is not possible
  3. Revert the scope configuration change to match the existing state

Example fix

// before
// scope changed: new subscription/resourceGroup/region/sandboxGroup, old state present -> error
// after
aspire destroy   # with previous scope configuration
aspire deploy    # now with new scope
Defensive patterns

Strategy: validation

Validate before calling

// Compare current scope against state section before deploying
bool ScopeMatches(state, sub, rg, region, group) =>
    string.Equals(state.SubscriptionId, sub, OrdinalIgnoreCase) &&
    string.Equals(state.ResourceGroupName, rg, OrdinalIgnoreCase) &&
    string.Equals(state.Region, region, OrdinalIgnoreCase) &&
    string.Equals(state.SandboxGroupName, group, OrdinalIgnoreCase);

Try / catch

try { DeploySandbox(...); } catch (InvalidOperationException ex) when (ex.Message.Contains("deployment scope changed")) { /* run aspire destroy with previous scope, then redeploy */ }

Prevention

When it happens

Trigger: Changing subscription ID, resource group name, region, or sandbox group name (case-insensitive comparison) in the sandbox configuration without destroying the existing sandbox deployment state.

Common situations: Moving a project to a different Azure subscription or region; renaming the resource group or sandbox group; switching between environments that share a state file.

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/c03c3bd30d78cc36. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs:2130

        var subscriptionId = stateSection.Data["SubscriptionId"]?.GetValue<string>();
        var resourceGroup = stateSection.Data["ResourceGroup"]?.GetValue<string>();
        var location = stateSection.Data["Location"]?.GetValue<string>();
        var sandboxGroup = stateSection.Data["SandboxGroup"]?.GetValue<string>();
        if (string.IsNullOrWhiteSpace(subscriptionId) ||
            string.IsNullOrWhiteSpace(resourceGroup) ||
            string.IsNullOrWhiteSpace(location) ||
            string.IsNullOrWhiteSpace(sandboxGroup))
        {
            return;
        }

        if (!string.Equals(subscriptionId, scope.SubscriptionId, StringComparison.OrdinalIgnoreCase) ||
            !string.Equals(resourceGroup, scope.ResourceGroupName, StringComparison.OrdinalIgnoreCase) ||
            !string.Equals(location, scope.Region, StringComparison.OrdinalIgnoreCase) ||
            !string.Equals(sandboxGroup, scope.SandboxGroupName, StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException(
                "The Azure sandbox group deployment scope changed while sandbox deployment state still exists. " +
                "Run 'aspire destroy' with the previous sandbox group configuration before deploying to the new scope.");
        }
    }

    internal static bool HasRemoteDeploymentState(DeploymentStateSection stateSection) =>
        !string.IsNullOrWhiteSpace(stateSection.Data["OwnerId"]?.GetValue<string>()) ||
        !string.IsNullOrWhiteSpace(stateSection.Data["SandboxId"]?.GetValue<string>()) ||
        !string.IsNullOrWhiteSpace(stateSection.Data["DiskImageId"]?.GetValue<string>());

    internal static string CreateSandboxUrlSummary(string currentUrl, string? retainedUrl)
    {
        if (string.IsNullOrWhiteSpace(retainedUrl) ||
            string.Equals(currentUrl, retainedUrl, StringComparison.Ordinal))
        {
            return $"[{currentUrl}]({currentUrl})";
        }

View on GitHub (pinned to 25830f84bd)