microsoft/aspire · error · InvalidOperationException
Azure sandbox group ' ' uses identity ' ' for both image…
Error message
Azure sandbox group '{Name}' uses identity '{userAssignedIdentity.Name}' for both image pulls and workload '{resource.Name}'. Use a dedicated image-pull identity so its AcrPull permission is not exposed to sandbox workloads. What it means
A compute resource's workload identity is the exact same identity instance as the sandbox group's image-pull (AcrPull) identity. Granting AcrPull to that identity and also running workloads under it would expose registry pull permission to sandbox code, so publishing is blocked until a dedicated image-pull identity is provided.
Solutions
- Provision a separate user-assigned managed identity solely for image pulls and set it via the sandbox group's image-pull identity (AcrPull) configuration.
- Give the compute resource its own AzureUserAssignedIdentityResource distinct from the image-pull identity.
- Search your app model for the identity's resource name and confirm it appears in only one of the two roles (image pull vs workload).
- If simplification is the goal, remember the separation is a security boundary: the AcrPull identity must never run workload code.
Example fix
// before
var mi = new AzureUserAssignedIdentityResource("app-mi");
sandboxGroup.WithImagePullIdentity(mi);
compute.ConfigureAppIdentity(new AppIdentityAnnotation(mi));
// after
var pullMi = new AzureUserAssignedIdentityResource("acr-pull-mi");
var appMi = new AzureUserAssignedIdentityResource("app-mi");
sandboxGroup.WithImagePullIdentity(pullMi);
compute.ConfigureAppIdentity(new AppIdentityAnnotation(appMi)); Defensive patterns
Strategy: validation
Validate before calling
if (ReferenceEquals(pullIdentity, workloadIdentity))
{
throw new InvalidOperationException("Image-pull identity must differ from every workload identity.");
} Type guard
bool IsDedicatedPullIdentity(AzureUserAssignedIdentityResource pull, AzureUserAssignedIdentityResource workload) => !ReferenceEquals(pull, workload);
Try / catch
try { publish(); } catch (InvalidOperationException ex) when (ex.Message.Contains("for both image pulls and workload")) { /* create a dedicated AcrPull identity and reconfigure */ } Prevention
- Provision a dedicated AcrPull identity per sandbox group as a standard template step.
- Never pass the same AzureUserAssignedIdentityResource instance to both sandbox identity options and compute app identity.
- Grep the model-building code for each identity resource name to confirm single-role usage.
When it happens
Trigger: Publishing when ReferenceEquals(imagePullIdentity, userAssignedIdentity) — the AzureSandboxGroupAcrPullIdentityAnnotation identity and the compute resource's AppIdentityAnnotation identity are the same AzureUserAssignedIdentityResource, and the sandbox group is not existing (the earlier existing-group check did not apply).
Common situations: Passing the same user-assigned identity to both the sandbox group's image-pull identity option and the workload's WithAppIdentity; constructing one identity resource and reusing it across sandbox-level and compute-level configuration to save a resource.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Azure sandbox group ' ' uses identity ' ' for both image…
- Compute resource ' ' uses an application identity type that…
- Compute resource ' ' uses managed identity ' ', but…
- No container registry associated with Azure sandbox group
- No container registry associated with Azure sandbox group
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/a6b3ed7716be596c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxGroupResource.cs:247
}
if (resource.TryGetLastAnnotation<AppIdentityAnnotation>(out var appIdentity))
{
if (appIdentity.IdentityResource is not AzureUserAssignedIdentityResource userAssignedIdentity)
{
throw new NotSupportedException(
$"Compute resource '{resource.Name}' uses an application identity type that Azure sandboxes do not support.");
}
if (this.IsExisting())
{
throw new InvalidOperationException(
$"Compute resource '{resource.Name}' uses managed identity '{userAssignedIdentity.Name}', but workload identities are not supported when publishing to existing Azure sandbox group '{Name}'.");
}
if (ReferenceEquals(imagePullIdentity, userAssignedIdentity))
{
throw new InvalidOperationException(
$"Azure sandbox group '{Name}' uses identity '{userAssignedIdentity.Name}' for both image pulls and workload '{resource.Name}'. " +
"Use a dedicated image-pull identity so its AcrPull permission is not exposed to sandbox workloads.");
}
AddWorkloadUserAssignedIdentity(userAssignedIdentity);
}
AzureSandboxContainerDeployment.ValidateSandboxCompatibility(resource);
resource.Annotations.Add(new ContainerBuildOptionsCallbackAnnotation(static buildOptions =>
{
// ADC requires a single Docker-format linux/amd64 manifest. Buildx's default OCI
// index with provenance attestations can produce a disk image with no bootable root filesystem.
buildOptions.Destination = ContainerImageDestination.Registry;
buildOptions.OutputPath = null;
buildOptions.ImageFormat = ContainerImageFormat.Docker;
buildOptions.TargetPlatform = ContainerTargetPlatform.LinuxAmd64;
}));View on GitHub (pinned to 25830f84bd)