microsoft/aspire · error · ArgumentException

A purge task with the name

Error message

A purge task with the name '{taskName}' already exists.

What it means

WithPurgeTask checks existing ACR tasks on the registry resource and throws ArgumentException when an explicitly supplied taskName collides with an existing task name (ordinal comparison). Auto-generated names use a numeric suffix to avoid collisions.

Solutions

  1. Use a unique taskName per WithPurgeTask call
  2. Omit taskName so the method auto-generates a suffixed name
  3. Rename or remove the pre-existing ACR task with the same name

Example fix

// before
.WithPurgeTask(taskName: "purge", schedule: "0 3 * * *", keep: 10)
.WithPurgeTask(taskName: "purge", schedule: "0 4 * * *", keep: 5)
// after
.WithPurgeTask(taskName: "purge-nightly", schedule: "0 3 * * *", keep: 10)
.WithPurgeTask(taskName: "purge-weekly", schedule: "0 4 * * 0", keep: 5)
Defensive patterns

Strategy: validation

Validate before calling

var nameInUse = registryResource.Infrastructure
    .GetResources().OfType<ContainerRegistryTask>()
    .Any(t => string.Equals(t.Name.Value, taskName, StringComparison.Ordinal));

Try / catch

try { env.WithPurgeTask(taskName: taskName, schedule: cron, keep: 10); }
catch (ArgumentException ex) when (ex.Message.Contains("already exists")) { log.LogError(ex, "Duplicate task name {Task}", taskName); }

Prevention

When it happens

Trigger: Calling WithPurgeTask twice with the same explicit taskName, or with a taskName that matches a task created elsewhere (another WithPurgeTask call, ARM/Bicep-defined task).

Common situations: Adding multiple purge schedules in a loop that reuses a constant name; a name collision with pre-existing infrastructure in the same Bicep module.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

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

        return builder.ConfigureInfrastructure(infra =>
        {
            var prefix = "purgeOldImages";

            var registry = infra.GetProvisionableResources().OfType<ContainerRegistryService>().Single();
            var allTasks = infra.GetProvisionableResources().OfType<ContainerRegistryTask>()
                .Where(t => t.Parent == registry)
                .ToList();
            var autoNamedTasks = allTasks
                .Where(t => t.Name.Value?.StartsWith(prefix, StringComparison.Ordinal) == true)
                .ToList();
            var taskIndex = autoNamedTasks.Count;

            if (!string.IsNullOrWhiteSpace(taskName))
            {
                if (allTasks.Any(t => string.Equals(t.Name.Value, taskName, StringComparison.Ordinal)))
                {
                    throw new ArgumentException($"A purge task with the name '{taskName}' already exists.", nameof(taskName));
                }
            }
            else
            {
                taskName = taskIndex == 0 ? prefix : $"{prefix}_{taskIndex}";
            }

            var bicepIdentifier = $"{prefix}_{taskIndex}";

            var purgeTaskCmdVariable = new ProvisioningVariable($"purgeTaskCmd_{taskIndex}", typeof(string))
            {
                Value = CreatePurgeTaskContent(filter, purgeAgo, keep)
            };
            infra.Add(purgeTaskCmdVariable);

            var purgeTask = new ContainerRegistryTask(bicepIdentifier)
            {
                Name = taskName,

View on GitHub (pinned to 25830f84bd)