{"record":{"id":"10c6aca041156f3c","repo":"microsoft/aspire","slug":"failed-to-retrieve-container-registry-endpoint","errorCode":null,"errorMessage":"Failed to retrieve container registry endpoint.","messagePattern":"Failed to retrieve container registry endpoint\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.ContainerRegistry/AzureContainerRegistryHelpers.cs","lineNumber":32,"sourceCode":"\n/// <summary>\n/// Helper methods for Azure Container Registry operations.\n/// </summary>\ninternal static class AzureContainerRegistryHelpers\n{\n    public static async Task LoginToRegistryAsync(IContainerRegistry registry, PipelineStepContext context)\n    {\n        var acrLoginService = context.Services.GetRequiredService<IAcrLoginService>();\n        var tokenCredentialProvider = context.Services.GetRequiredService<ITokenCredentialProvider>();\n\n        // Find the AzureEnvironmentResource from the application model\n        var azureEnvironment = context.Model.Resources.OfType<AzureEnvironmentResource>().FirstOrDefault() ??\n            throw new InvalidOperationException(\"AzureEnvironmentResource must be present in the application model.\");\n        var registryName = await registry.Name.GetValueAsync(context.CancellationToken).ConfigureAwait(false) ??\n            throw new InvalidOperationException(\"Failed to retrieve container registry information.\");\n\n        var registryEndpoint = await registry.Endpoint.GetValueAsync(context.CancellationToken).ConfigureAwait(false) ??\n            throw new InvalidOperationException(\"Failed to retrieve container registry endpoint.\");\n\n        var loginTask = await context.ReportingStep.CreateTaskAsync(\n            new MarkdownString($\"Logging in to **{registryName}**\"),\n            context.CancellationToken).ConfigureAwait(false);\n        await using (loginTask.ConfigureAwait(false))\n        {\n            try\n            {\n                // Get tenant ID from the provisioning context (always available from subscription)\n                var provisioningContext = await azureEnvironment.ProvisioningContextTask.Task.ConfigureAwait(false);\n                var tenantId = provisioningContext.Tenant.TenantId?.ToString()\n                    ?? throw new InvalidOperationException(\"Tenant ID is required for ACR authentication but was not available in provisioning context.\");\n\n                // Use the ACR login service to perform authentication\n                await acrLoginService.LoginAsync(\n                    registryEndpoint,\n                    tenantId,\n                    tokenCredentialProvider.TokenCredential,","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.ContainerRegistry/AzureContainerRegistryHelpers.cs#L14-L50","documentation":"LoginToRegistryAsync resolves the registry's Endpoint value asynchronously before authenticating with 'az acr login'-style flows; a null endpoint means the login target is unknown, so the library throws InvalidOperationException. The endpoint is normally produced by provisioning outputs (login server URL).","triggerScenarios":"Awaiting registry.Endpoint.GetValueAsync yields null because the registry resource's endpoint parameter was never populated, typically when provisioning hasn't run or a custom resource construction skipped the endpoint assignment.","commonSituations":"Publish/run without completing Azure provisioning so the login-server output is absent; manually constructed registry resources in tests or custom pipelines lacking the Endpoint parameter; typos when wiring endpoint references between resources.","solutions":["Let standard provisioning populate the endpoint by running through the normal publish/deploy flow rather than invoking login before provisioning completes.","If constructing the resource manually, assign registry.Endpoint from the provisioning context's container registry endpoint output.","Verify the Azure environment/subscription setup completed successfully so the login server is available.","Log or inspect the registry resource's parameter values at login time to see which reference is null."],"exampleFix":"// before\nawait loginService.LoginAsync(endpoint /* null */, tenantId, credential);\n// after\nvar endpoint = await registry.Endpoint.GetValueAsync(ct) ?? throw new InvalidOperationException(\"Registry endpoint missing; ensure provisioning completed.\");","handlingStrategy":"validation","validationCode":"var endpoint = await registry.Endpoint.GetValueAsync(ct);\nif (string.IsNullOrEmpty(endpoint))\n{\n    throw new InvalidOperationException(\"Registry endpoint missing; ensure provisioning completed before login.\");\n}","typeGuard":"bool endpointResolved = await registry.Endpoint.GetValueAsync(ct) is string e && !string.IsNullOrEmpty(e);","tryCatchPattern":"try\n{\n    await LoginToRegistryAsync(registry, context);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"registry endpoint\"))\n{\n    logger.LogError(\"Registry endpoint was null; confirm Azure provisioning produced the login server.\");\n    throw;\n}","preventionTips":["Do not invoke registry login before provisioning outputs exist.","Verify publish steps complete without errors so the login-server output is generated.","When constructing registry resources manually, always assign the Endpoint parameter."],"tags":["azure","container-registry","null-value","provisioning"],"backgroundTag":"missing-required-config-field","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"}