microsoft/aspire · error · ArgumentOutOfRangeException

Keep must be greater than zero.

Error message

Keep must be greater than zero.

What it means

WithPurgeTask's keep parameter controls how many images a purge retains, and values below 1 make no sense (nothing or negative retention). The method throws ArgumentOutOfRangeException with the actual keep value when keep < 1.

Solutions

  1. Pass keep >= 1 (at least 1 image retained)
  2. Clamp computed values: Math.Max(1, computedKeep)
  3. Fix configuration so the keep setting holds a positive integer

Example fix

// before
.WithPurgeTask(schedule: "0 3 * * *", keep: 0)
// after
.WithPurgeTask(schedule: "0 3 * * *", keep: 5)
Defensive patterns

Strategy: validation

Validate before calling

if (keep < 1) throw new ArgumentOutOfRangeException(nameof(keep), keep, "Keep must be >= 1.");

Try / catch

try { env.WithPurgeTask(schedule: cron, keep: keep); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "keep") { log.LogError(ex, "Invalid keep value"); }

Prevention

When it happens

Trigger: Calling WithPurgeTask with keep set to 0 or a negative number, or with a computed value that underflows to <= 0.

Common situations: Configuring 'delete everything' by passing 0; a config value or calculation producing a negative count; swapping parameter order so a limit lands in keep.

Related errors


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

Appendix: source

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

        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrWhiteSpace(schedule);
        schedule = schedule.Trim();

        try
        {
            _ = CrontabSchedule.Parse(schedule, new CrontabSchedule.ParseOptions { IncludingSeconds = false });
        }
        catch (CrontabException ex)
        {
            throw new ArgumentException(
                $"The schedule '{schedule}' is not a valid five-part cron expression (minute hour day-of-month month day-of-week). {ex.Message}",
                nameof(schedule),
                ex);
        }

        if (keep < 1)
        {
            throw new ArgumentOutOfRangeException(nameof(keep), keep, "Keep must be greater than zero.");
        }

        var purgeAgo = FormatAgo(ago ?? TimeSpan.Zero);

        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))

View on GitHub (pinned to 25830f84bd)