{"record":{"id":"c1cd33201f5b5061","repo":"microsoft/aspire","slug":"propertyname-must-be-a-non-negative-whole-second-duration","errorCode":null,"errorMessage":"{propertyName} must be a non-negative whole-second duration.","messagePattern":"(.+?) must be a non-negative whole-second duration\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs","lineNumber":615,"sourceCode":"            AutoDeletePolicy = hasAutoDeleteOverride ? new AzureDevComputeSandboxAutoDeletePolicy\n            {\n                Enabled = options!.AutoDeleteEnabled!.Value,\n                DeleteIntervalInSeconds = ToInt64Seconds(options.AutoDeleteInterval, nameof(AzureSandboxOptions.AutoDeleteInterval)),\n                Trigger = options.AutoDeleteTrigger?.ToString()\n            } : null\n        };\n    }\n\n    private static int? ToInt32Seconds(TimeSpan? value, string propertyName)\n    {\n        if (value is null)\n        {\n            return null;\n        }\n\n        if (value < TimeSpan.Zero || value.Value.Ticks % TimeSpan.TicksPerSecond != 0)\n        {\n            throw new InvalidOperationException($\"{propertyName} must be a non-negative whole-second duration.\");\n        }\n\n        var seconds = value.Value.Ticks / TimeSpan.TicksPerSecond;\n        return seconds <= int.MaxValue\n            ? (int)seconds\n            : throw new InvalidOperationException($\"{propertyName} exceeds the maximum supported ADC interval.\");\n    }\n\n    private static long? ToInt64Seconds(TimeSpan? value, string propertyName)\n    {\n        if (value is null)\n        {\n            return null;\n        }\n\n        if (value < TimeSpan.Zero || value.Value.Ticks % TimeSpan.TicksPerSecond != 0)\n        {\n            throw new InvalidOperationException($\"{propertyName} must be a non-negative whole-second duration.\");","sourceCodeStart":597,"sourceCodeEnd":633,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs#L597-L633","documentation":"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.","triggerScenarios":"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).","commonSituations":"Copying a duration from config that was specified in milliseconds, or computing a timeout with fractional seconds (e.g. minutes * 1.5).","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."],"exampleFix":"// before\npolicy.IdleTimeout = TimeSpan.FromMinutes(4.5);\n// after\npolicy.IdleTimeout = TimeSpan.FromMinutes(4);","handlingStrategy":"validation","validationCode":"static TimeSpan WholeNonNegativeSeconds(TimeSpan t, string name)\n{\n    if (t < TimeSpan.Zero || t.Ticks % TimeSpan.TicksPerSecond != 0)\n        throw new ArgumentException($\"{name} must be a non-negative whole number of seconds.\");\n    return t;\n}","typeGuard":null,"tryCatchPattern":"try { policy.IdleTimeout = ToSeconds(cfg.Value); }\ncatch (InvalidOperationException ex) { /* round/floor the config duration to whole seconds and retry */ }","preventionTips":["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."],"tags":["azure","sandboxes","duration","validation"],"backgroundTag":"invalid-duration-format","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}