microsoft/aspire · error · ArgumentOutOfRangeException
Ago must be at least 1 minute to be compatible with acr…
Error message
Ago must be at least 1 minute to be compatible with acr purge.
What it means
FormatAgo converts a TimeSpan into the --ago flag value for the Azure 'acr purge' command, which quantizes age into units no smaller than a minute. The library throws ArgumentOutOfRangeException when given a nonzero TimeSpan smaller than one minute because acr purge cannot express such a threshold.
Solutions
- Pass a TimeSpan of at least one minute (e.g. TimeSpan.FromMinutes(1) or larger such as FromHours(24)).
- If you intend 'purge everything regardless of age', pass TimeSpan.Zero explicitly, which formats as '0d'.
- Clamp the value before calling: if the computed TimeSpan is under one minute, raise it to one minute or skip the purge.
- If you need sub-minute retention semantics, do the deletion directly with the Azure SDK (container registry client) instead of acr purge.
Example fix
// before var ago = TimeSpan.FromSeconds(45); // throws PurgeImages(registry, ago); // after var ago = TimeSpan.FromMinutes(1); // minimum acr purge supports PurgeImages(registry, ago);
Defensive patterns
Strategy: validation
Validate before calling
if (ago != TimeSpan.Zero && ago.TotalMinutes < 1)
{
throw new ArgumentOutOfRangeException(nameof(ago), "Ago must be at least 1 minute for acr purge; use TimeSpan.Zero for no age filter.");
} Try / catch
try
{
PurgeImages(registry, ago);
}
catch (ArgumentOutOfRangeException ex)
{
logger.LogWarning(ex, "Purge ago {Ago} below acr purge minimum; clamping to 1 minute.", ago);
ago = TimeSpan.FromMinutes(1);
} Prevention
- Treat one minute as the minimum quantum for acr purge age values.
- Use TimeSpan.Zero explicitly for 'no age restriction' instead of tiny durations.
- Unit-test age computation helpers to assert >= 1 minute output for nonzero values.
When it happens
Trigger: Calling the ACR purge/purge-images helper (via purgeAgo) with a TimeSpan whose TotalMinutes < 1 and which is not exactly TimeSpan.Zero, e.g. TimeSpan.FromSeconds(30) or a computed 'now - lastModified' gap under a minute.
Common situations: Configuring a retention/purge policy with a very short maxAge like 30 seconds; a test that builds an ago value from a recent timestamp so the delta is sub-minute; misreading '--ago' units as seconds instead of minutes/hours.
Related errors
- Keep must be greater than zero.
- 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/cfe450468cce7090.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.ContainerRegistry/AzureContainerRegistryExtensions.cs:330
""".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).
/// </summary>
/// <remarks>
/// From the docs: https://learn.microsoft.com/azure/container-registry/container-registry-auto-purge#example-scheduled-purge-of-multiple-repositories-in-a-registry
/// A Go-style duration string to indicate a duration beyond which images are deleted. The duration consists of a sequence
/// of one or more decimal numbers, each with a unit suffix. Valid time units include "d" for days, "h" for hours, and "m"
/// for minutes. For example, --ago 2d3h6m selects all filtered images last modified more than two days, 3 hours, and 6 minutes
/// ago, and --ago 1.5h selects images last modified more than 1.5 hours ago.
/// </remarks>
private static string FormatAgo(TimeSpan ago)
{
if (ago.TotalMinutes < 1 && ago != TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(ago), ago, "Ago must be at least 1 minute to be compatible with acr purge.");
}
if (ago == TimeSpan.Zero)
{
return "0d";
}
var sb = new StringBuilder();
if (ago.Days > 0)
{
sb.Append(CultureInfo.InvariantCulture, $"{ago.Days}d");
}
if (ago.Hours > 0)
{
sb.Append(CultureInfo.InvariantCulture, $"{ago.Hours}h");
}View on GitHub (pinned to 25830f84bd)