microsoft/aspire · error · InvalidOperationException
Tenant ID is required for ACR authentication but was not…
Error message
Tenant ID is required for ACR authentication but was not available in provisioning context.
What it means
ACR token authentication requires the Azure AD tenant ID, which LoginToRegistryAsync reads from the AzureEnvironmentResource's ProvisioningContextTask. If the provisioning context exists but its Tenant or TenantId is null, the library throws InvalidOperationException because ACR login cannot proceed without a tenant.
Solutions
- Ensure provisioning runs the normal tenant resolution path so Tenant.TenantId is populated from the subscription.
- If constructing the provisioning context manually (tests, custom tooling), set Tenant = new TenantInfo { TenantId = ... } (or equivalent) before login.
- Confirm the Azure credential/subscription used for provisioning is valid and resolves a tenant.
- Pass an explicit tenant via your provisioning options if the automatic discovery returns none.
Example fix
// before
var context = new AzureProvisioningContext(options) { Tenant = null };
// after
var context = new AzureProvisioningContext(options);
context.Tenant = new TenantInfo { TenantId = Guid.Parse("00000000-0000-0000-0000-000000000000") }; Defensive patterns
Strategy: try-catch
Validate before calling
var ctx = await azureEnvironment.ProvisioningContextTask.Task;
var tenantId = ctx.Tenant?.TenantId?.ToString();
if (string.IsNullOrEmpty(tenantId))
{
throw new InvalidOperationException("Provisioning context has no tenant; cannot authenticate to ACR.");
} Try / catch
try
{
await LoginToRegistryAsync(registry, context);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Tenant ID"))
{
logger.LogError("Tenant ID unavailable; check Azure credentials and provisioning tenant resolution.");
throw;
} Prevention
- Use valid Azure credentials whose subscription resolves a tenant.
- Never stub ProvisioningContextTask with an empty Tenant in tests that exercise login.
- Keep provisioning flows on the standard path so Tenant.TenantId is populated.
When it happens
Trigger: ProvisioningContextTask.Task completes with a context whose Tenant is null or Tenant.TenantId is null — e.g. a custom/fake provisioning context, or a provisioning pipeline that skipped tenant resolution from the subscription.
Common situations: Testing harnesses that stub ProvisioningContextTask with a partially populated AzureProvisioningOptions/context; running against an unusual subscription setup where tenant data wasn't fetched; manually creating the provisioning context without going through the normal tenant discovery step.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Could not find tenant id
- Failed to retrieve container registry endpoint.
- A purge task with the name
- A of type cannot be assigned to a BicepValue< >.
- Ago must be at least 1 minute to be compatible with acr…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/757420cd390d0f98.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.ContainerRegistry/AzureContainerRegistryHelpers.cs:44
var azureEnvironment = context.Model.Resources.OfType<AzureEnvironmentResource>().FirstOrDefault() ??
throw new InvalidOperationException("AzureEnvironmentResource must be present in the application model.");
var registryName = await registry.Name.GetValueAsync(context.CancellationToken).ConfigureAwait(false) ??
throw new InvalidOperationException("Failed to retrieve container registry information.");
var registryEndpoint = await registry.Endpoint.GetValueAsync(context.CancellationToken).ConfigureAwait(false) ??
throw new InvalidOperationException("Failed to retrieve container registry endpoint.");
var loginTask = await context.ReportingStep.CreateTaskAsync(
new MarkdownString($"Logging in to **{registryName}**"),
context.CancellationToken).ConfigureAwait(false);
await using (loginTask.ConfigureAwait(false))
{
try
{
// Get tenant ID from the provisioning context (always available from subscription)
var provisioningContext = await azureEnvironment.ProvisioningContextTask.Task.ConfigureAwait(false);
var tenantId = provisioningContext.Tenant.TenantId?.ToString()
?? throw new InvalidOperationException("Tenant ID is required for ACR authentication but was not available in provisioning context.");
// Use the ACR login service to perform authentication
await acrLoginService.LoginAsync(
registryEndpoint,
tenantId,
tokenCredentialProvider.TokenCredential,
context.CancellationToken).ConfigureAwait(false);
await loginTask.CompleteAsync(
new MarkdownString($"Successfully logged in to **{registryEndpoint}**"),
CompletionState.Completed,
context.CancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
await loginTask.FailAsync(
new MarkdownString($"Login to ACR **{registryEndpoint}** failed: {ex.Message}"),
context.CancellationToken).ConfigureAwait(false);View on GitHub (pinned to 25830f84bd)