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
- Pass keep >= 1 (at least 1 image retained)
- Clamp computed values: Math.Max(1, computedKeep)
- 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
- Clamp computed retention values with Math.Max(1, value)
- Validate config integers before passing them in
- Never encode 'delete all' as keep=0; it is unsupported
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
- Ago must be at least 1 minute to be compatible with acr…
- A purge task with the name
- AzureEnvironmentResource must be present in the application…
- Connector Namespace resource names must contain between 2…
- Failed to retrieve container registry endpoint.
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)