microsoft/aspire · error · ArgumentException

' ' is not a valid AzureContainerRegistryRole value.

Error message

'{roles[i]}' is not a valid AzureContainerRegistryRole value.

What it means

WithRoleAssignments maps each AzureContainerRegistryRole enum value to an Azure Provisioning ContainerRegistryBuiltInRole; the switch's default arm throws ArgumentException naming the offending element when the roles array contains an undefined/out-of-range enum value.

Solutions

  1. Pass only valid AzureContainerRegistryRole members (AcrPull, AcrPush, AcrDelete, AcrImageSigner, AcrQuarantineReader/Writer, etc.)
  2. Validate with Enum.IsName/Enum.IsDefined before building the array
  3. Fix the config or deserialization mapping that produced the bogus value

Example fix

// before
var role = (AzureContainerRegistryRole)999;
.WithRoleAssignments(target, new[] { role })
// after
if (!Enum.IsDefined(role)) throw new InvalidOperationException($"Unknown role {role}");
.WithRoleAssignments(target, new[] { AzureContainerRegistryRole.AcrPull })
Defensive patterns

Strategy: validation

Validate before calling

foreach (var role in roles)
    if (!Enum.IsDefined(typeof(AzureContainerRegistryRole), role))
        throw new ArgumentException($"'{role}' is not a valid {nameof(AzureContainerRegistryRole)} value.");

Type guard

bool IsValidRole(AzureContainerRegistryRole role) => Enum.IsDefined(typeof(AzureContainerRegistryRole), role);

Try / catch

try { env.WithRoleAssignments(target, roles); }
catch (ArgumentException ex) when (ex.ParamName == "roles") { log.LogError(ex, "Invalid role value"); }

Prevention

When it happens

Trigger: Passing an enum value not defined by AzureContainerRegistryRole (e.g. an invalid cast of an int) in the roles argument of WithRoleAssignments.

Common situations: Casting raw ints from config into the enum without validation; deserializing a role name that doesn't match any member; a stale enum value after a package version change.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/b2038ee50609a54c. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Azure.ContainerRegistry/AzureContainerRegistryExtensions.cs:299

        where T : IResource
    {
        if (roles is null || roles.Length == 0)
        {
            return builder.WithRoleAssignments(target, Array.Empty<ContainerRegistryBuiltInRole>());
        }

        var builtInRoles = new ContainerRegistryBuiltInRole[roles.Length];
        for (var i = 0; i < roles.Length; i++)
        {
            builtInRoles[i] = roles[i] switch
            {
                AzureContainerRegistryRole.AcrDelete => ContainerRegistryBuiltInRole.AcrDelete,
                AzureContainerRegistryRole.AcrImageSigner => ContainerRegistryBuiltInRole.AcrImageSigner,
                AzureContainerRegistryRole.AcrPull => ContainerRegistryBuiltInRole.AcrPull,
                AzureContainerRegistryRole.AcrPush => ContainerRegistryBuiltInRole.AcrPush,
                AzureContainerRegistryRole.AcrQuarantineReader => ContainerRegistryBuiltInRole.AcrQuarantineReader,
                AzureContainerRegistryRole.AcrQuarantineWriter => ContainerRegistryBuiltInRole.AcrQuarantineWriter,
                _ => throw new ArgumentException($"'{roles[i]}' is not a valid {nameof(AzureContainerRegistryRole)} value.", nameof(roles))
            };
        }

        return builder.WithRoleAssignments(target, builtInRoles);
    }

    private static string CreatePurgeTaskContent(string? filter, string ago, int keep)
    {
        return $"""
            version: v1.1.0
            steps:
            - cmd: acr purge --filter '{filter ?? ".*:.*"}' --ago {ago} --keep {keep}
            """.ReplaceLineEndings("\n");
    }

    /// <summary>
    /// Formats a <see cref="TimeSpan"/> into a Go-style duration string compatible with <c>acr purge --ago</c>.
    /// Valid units: <c>d</c> (days), <c>h</c> (hours), <c>m</c> (minutes).

View on GitHub (pinned to 25830f84bd)