{"record":{"id":"d1c84ebfa5fd06c9","repo":"microsoft/aspire","slug":"existing-azure-sandbox-group-sandboxgroup-name-requires-a","errorCode":null,"errorMessage":"Existing Azure sandbox group '{sandboxGroup.Name}' requires a user-assigned ACR pull identity. Call 'WithAcrPullIdentity' with an identity that is already attached to the sandbox group and has AcrPull on the configured registry.","messagePattern":"Existing Azure sandbox group '(.+?)' requires a user-assigned ACR pull identity\\. Call 'WithAcrPullIdentity' with an identity that is already attached to the sandbox group and has AcrPull on the configured registry\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs","lineNumber":58,"sourceCode":"    [AspireExport]\n    [Experimental(\"ASPIREAZURE001\", UrlFormat = \"https://aka.ms/aspire/diagnostics/{0}\")]\n    public static IResourceBuilder<AzureSandboxGroupResource> AddAzureSandboxGroup(this IDistributedApplicationBuilder builder, [ResourceName] string name)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrWhiteSpace(name);\n\n        static void ConfigureInfrastructure(AzureResourceInfrastructure infrastructure)\n        {\n            var sandboxResource = (AzureSandboxGroupResource)infrastructure.AspireResource;\n            UserAssignedIdentity? newImagePullIdentity = null;\n            BicepValue<string> imagePullIdentityId;\n            BicepValue<string> imagePullIdentityClientId;\n            if (sandboxResource.TryGetLastAnnotation<AzureSandboxGroupAcrPullIdentityAnnotation>(out var imagePullIdentityAnnotation))\n            {\n                if (sandboxResource.IsExisting() &&\n                    (imagePullIdentityAnnotation.IsAspireManaged || !imagePullIdentityAnnotation.Identity.IsExisting()))\n                {\n                    throw CreateExistingSandboxGroupMissingAcrPullIdentityException(sandboxResource);\n                }\n\n                imagePullIdentityId = imagePullIdentityAnnotation.Identity.Id.AsProvisioningParameter(infrastructure);\n                imagePullIdentityClientId = imagePullIdentityAnnotation.Identity.ClientId.AsProvisioningParameter(infrastructure);\n            }\n            else\n            {\n                if (sandboxResource.IsExisting())\n                {\n                    throw CreateExistingSandboxGroupMissingAcrPullIdentityException(sandboxResource);\n                }\n\n                newImagePullIdentity = new UserAssignedIdentity(\n                    Infrastructure.NormalizeBicepIdentifier($\"{sandboxResource.Name}_mi\"));\n                infrastructure.Add(newImagePullIdentity);\n                imagePullIdentityId = newImagePullIdentity.Id.ToBicepExpression();\n                imagePullIdentityClientId = newImagePullIdentity.ClientId.ToBicepExpression();\n            }","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs#L40-L76","documentation":"AddAzureSandboxGroup requires that existing (non-Aspire-managed) Azure sandbox groups supply a user-assigned ACR pull identity via WithAcrPullIdentity. When an AcrPull identity annotation exists but is Aspire-managed or references a non-existing identity resource, the extension throws because Aspire cannot attach a new managed identity to a group it does not own. The identity must already be attached to the sandbox group and have AcrPull on the registry.","triggerScenarios":"AddAzureSandboxGroup on a sandbox resource where sandboxResource.IsExisting() is true and the AzureSandboxGroupAcrPullIdentityAnnotation is IsAspireManaged == true or its Identity.IsExisting() is false.","commonSituations":"Configuring an existing sandbox group but letting Aspire create a new user-assigned identity for ACR pull; using the default managed identity path against a pre-existing group; passing an identity resource that is newly created rather than the existing attached one.","solutions":["Call WithAcrPullIdentity with an existing user-assigned identity already attached to the sandbox group.","Grant that identity the AcrPull role on the configured container registry.","Verify the identity passed is marked existing (Identity.IsExisting() == true), not a new Aspire-managed identity.","If the group can be Aspire-managed instead, drop AsExisting so Aspire provisions and attaches the identity itself."],"exampleFix":"// before (new/managed identity on an existing group)\nvar group = builder.AddAzureSandboxGroup(\"group\", existing).WithAcrPullIdentity(newIdentity);\n// after\nvar existingIdentity = builder.AddUserAssignedIdentity(\"acrPullIdentity\").AsExisting(identityId, clientId);\nvar group = builder.AddAzureSandboxGroup(\"group\", existing)\n    .WithAcrPullIdentity(existingIdentity); // already attached + AcrPull granted","handlingStrategy":"validation","validationCode":"// before AddAzureSandboxGroup on an existing group, ensure the identity is existing\nvar identityOk = sandboxResource.IsExisting()\n    && sandboxResource.TryGetLastAnnotation<AzureSandboxGroupAcrPullIdentityAnnotation>(out var a)\n    && !a.IsAspireManaged\n    && a.Identity.IsExisting();\nif (sandboxResource.IsExisting() && !identityOk)\n{\n    // call WithAcrPullIdentity with an existing attached identity first\n}","typeGuard":"static bool HasValidExistingPullIdentity(IResource sandbox) =>\n    sandbox.TryGetLastAnnotation<AzureSandboxGroupAcrPullIdentityAnnotation>(out var a)\n    && !a.IsAspireManaged\n    && a.Identity.IsExisting();","tryCatchPattern":"try\n{\n    var group = builder.AddAzureSandboxGroup(\"group\", existing);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ACR pull identity\"))\n{\n    // reconfigure with an existing identity attached to the group, then retry\n}","preventionTips":["Always pair AsExisting sandbox groups with WithAcrPullIdentity(existingIdentity).","Grant AcrPull on the registry to the identity before wiring it in.","Attach the identity to the sandbox group outside Aspire; Aspire will not attach it for existing groups.","Prefer Aspire-managed groups when you want Aspire to provision the pull identity."],"tags":["azure","sandbox","identity","acr"],"backgroundTag":"invalid-argument-value","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"}