microsoft/aspire · error · InvalidOperationException
must be a non-negative whole-second duration.
Error message
{propertyName} must be a non-negative whole-second duration. What it means
ToInt32Seconds converts a nullable TimeSpan into whole seconds for an Azure Dev Compute (ADC) lifecycle policy field. It rejects negative values and any value with sub-second precision, throwing InvalidOperationException naming the offending property.
Solutions
- Round the duration to whole seconds: use TimeSpan.FromSeconds(Math.Round(value.TotalSeconds)) or TimeSpan.FromMinutes/Hours with integer amounts.
- Ensure the value is non-negative before assigning it to the policy property.
- If the value exceeds int.MaxValue seconds, use the corresponding int64-accepting property instead.
Example fix
// before policy.IdleTimeout = TimeSpan.FromMinutes(4.5); // after policy.IdleTimeout = TimeSpan.FromMinutes(4);
Defensive patterns
Strategy: validation
Validate before calling
static TimeSpan WholeNonNegativeSeconds(TimeSpan t, string name)
{
if (t < TimeSpan.Zero || t.Ticks % TimeSpan.TicksPerSecond != 0)
throw new ArgumentException($"{name} must be a non-negative whole number of seconds.");
return t;
} Try / catch
try { policy.IdleTimeout = ToSeconds(cfg.Value); }
catch (InvalidOperationException ex) { /* round/floor the config duration to whole seconds and retry */ } Prevention
- Build durations with FromSeconds/FromMinutes using integer arguments.
- Normalize config-supplied durations to whole seconds before assignment.
- Assert durations are non-negative at config-load time.
When it happens
Trigger: Setting a lifecycle policy property (e.g. idle timeout, retention interval) via CreateLifecyclePolicy to a TimeSpan that is negative or contains milliseconds/ticks, such as TimeSpan.FromSeconds(30.5) or TimeSpan.FromMilliseconds(1500).
Common situations: Copying a duration from config that was specified in milliseconds, or computing a timeout with fractional seconds (e.g. minutes * 1.5).
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- exceeds the maximum supported ADC interval.
- ADC request ' ' returned an incomplete response.
- App Service configuration validation failed. See errors…
- At least one connector operation must be explicitly…
- Azure sandbox group ' ' returned an invalid resource ID ' '.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/c1cd33201f5b5061.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs:615
AutoDeletePolicy = hasAutoDeleteOverride ? new AzureDevComputeSandboxAutoDeletePolicy
{
Enabled = options!.AutoDeleteEnabled!.Value,
DeleteIntervalInSeconds = ToInt64Seconds(options.AutoDeleteInterval, nameof(AzureSandboxOptions.AutoDeleteInterval)),
Trigger = options.AutoDeleteTrigger?.ToString()
} : null
};
}
private static int? ToInt32Seconds(TimeSpan? value, string propertyName)
{
if (value is null)
{
return null;
}
if (value < TimeSpan.Zero || value.Value.Ticks % TimeSpan.TicksPerSecond != 0)
{
throw new InvalidOperationException($"{propertyName} must be a non-negative whole-second duration.");
}
var seconds = value.Value.Ticks / TimeSpan.TicksPerSecond;
return seconds <= int.MaxValue
? (int)seconds
: throw new InvalidOperationException($"{propertyName} exceeds the maximum supported ADC interval.");
}
private static long? ToInt64Seconds(TimeSpan? value, string propertyName)
{
if (value is null)
{
return null;
}
if (value < TimeSpan.Zero || value.Value.Ticks % TimeSpan.TicksPerSecond != 0)
{
throw new InvalidOperationException($"{propertyName} must be a non-negative whole-second duration.");View on GitHub (pinned to 25830f84bd)