microsoft/aspire · error · InvalidOperationException
Azure sandbox group ' ' uses identity ' ' for both image…
Error message
Azure sandbox group '{Name}' uses identity '{imagePullIdentity.Name}' for both image pulls and workloads. Use a dedicated image-pull identity so its AcrPull permission is not exposed to sandbox workloads. What it means
The identity designated for pulling container images from the registry (with AcrPull) is also listed as a workload identity of the sandbox group. Because workload code could run under that identity and gain registry pull (and potentially sensitive registry) access, the library refuses to publish until a dedicated image-pull identity is used.
Solutions
- Create a separate user-assigned managed identity exclusively for image pulls and configure it as the sandbox group's AcrPull identity.
- Ensure each compute resource's app identity is a distinct identity not referenced by the AzureSandboxGroupAcrPullIdentityAnnotation.
- Audit your publish model for identity reuse: list the sandbox group's image-pull identity and every workload identity and confirm there is no overlap.
- If using an existing identity everywhere, provision a second identity and grant only it the AcrPull role on the registry.
Example fix
// before
var shared = new AzureUserAssignedIdentityResource("shared-mi");
sandboxGroup.WithImagePullIdentity(shared);
compute.WithAppIdentity(shared);
// after
var pullIdentity = new AzureUserAssignedIdentityResource("acr-pull-mi");
sandboxGroup.WithImagePullIdentity(pullIdentity);
compute.WithAppIdentity(new AzureUserAssignedIdentityResource("workload-mi")); Defensive patterns
Strategy: validation
Validate before calling
var pull = sandboxGroup.GetImagePullIdentity(); // via AzureSandboxGroupAcrPullIdentityAnnotation
if (pull is not null && sandboxGroup.WorkloadUserAssignedIdentities.Contains(pull))
{
throw new InvalidOperationException("Image-pull identity must be distinct from workload identities.");
} Type guard
var pullIdentity = resource.TryGetLastAnnotation<AzureSandboxGroupAcrPullIdentityAnnotation>(out var a) ? a.Identity : null;
Try / catch
try { publish(); } catch (InvalidOperationException ex) when (ex.Message.Contains("for both image pulls and workloads")) { /* provision a dedicated AcrPull identity and update options */ } Prevention
- Keep one identity per purpose: one for AcrPull, one per workload.
- Name identities explicitly (e.g. acr-pull-mi vs app-mi) to avoid accidental reuse.
- Review identity configuration in PublishAsAzureSandbox options and WithAppIdentity calls together during code review.
When it happens
Trigger: Publishing when the AzureSandboxGroupAcrPullIdentityAnnotation identity is contained in WorkloadUserAssignedIdentities — e.g. the same user-assigned managed identity was supplied both as the AcrPull identity (via the sandbox group's image-pull identity configuration) and as the app identity of a compute resource.
Common situations: Reusing one managed identity for everything in the sandbox group to simplify setup; copying the same identity resource into PublishAsAzureSandbox identity options and the compute resource's WithAppIdentity/ConfigureAppIdentity; sharing a pre-existing identity across sandbox-level and workload-level configuration.
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/91e380eec191fead.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxGroupResource.cs:205
return;
}
if (this.HasAnnotationOfType<ContainerRegistryReferenceAnnotation>() &&
DefaultContainerRegistry is not null)
{
context.Model.Resources.Remove(DefaultContainerRegistry);
DefaultContainerRegistry = null;
}
var containerRegistry = ContainerRegistry ??
throw new InvalidOperationException($"No container registry associated with Azure sandbox group '{Name}'. This should have been added automatically.");
var imagePullIdentity = this.TryGetLastAnnotation<AzureSandboxGroupAcrPullIdentityAnnotation>(out var imagePullIdentityAnnotation)
? imagePullIdentityAnnotation.Identity
: null;
if (imagePullIdentity is not null && WorkloadUserAssignedIdentities.Contains(imagePullIdentity))
{
throw new InvalidOperationException(
$"Azure sandbox group '{Name}' uses identity '{imagePullIdentity.Name}' for both image pulls and workloads. " +
"Use a dedicated image-pull identity so its AcrPull permission is not exposed to sandbox workloads.");
}
var computeEnvironments = context.Model.Resources.OfType<IComputeEnvironmentResource>().ToList();
var canClaimUnassignedComputeResources = computeEnvironments.Count == 1 && ReferenceEquals(computeEnvironments[0], this);
foreach (var resource in context.Model.GetComputeResources())
{
var resourceComputeEnvironment = resource.GetComputeEnvironment();
if (resourceComputeEnvironment is null && !canClaimUnassignedComputeResources)
{
continue;
}
if (resourceComputeEnvironment is not null && resourceComputeEnvironment != this)
{
continue;View on GitHub (pinned to 25830f84bd)