{"record":{"id":"3d9207c9e168d5a3","repo":"HangfireIO/Hangfire","slug":"timeout-value-should-be-equal-to-or-greater-than-z","errorCode":null,"errorMessage":"Timeout value should be equal to or greater than zero.","messagePattern":"Timeout value should be equal to or greater than zero\\.","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.SqlServer/ExpirationManager.cs","lineNumber":59,"sourceCode":"        \n        private static readonly string[] ProcessedTables =\n        {\n            \"AggregatedCounter\",\n            \"Job\",\n            \"List\",\n            \"Set\",\n            \"Hash\",\n        };\n\n        private readonly ILog _logger = LogProvider.For<ExpirationManager>();\n        private readonly SqlServerStorage _storage;\n        private readonly TimeSpan _stateExpirationTimeout;\n        private readonly TimeSpan _checkInterval;\n\n        public ExpirationManager(SqlServerStorage storage, TimeSpan stateExpirationTimeout, TimeSpan checkInterval)\n        {\n            if (storage == null) throw new ArgumentNullException(nameof(storage));\n            if (stateExpirationTimeout < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(stateExpirationTimeout), \"Timeout value should be equal to or greater than zero.\");\n            if (checkInterval <= TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(checkInterval), \"Timeout value should be greater than zero.\");\n\n            _storage = storage;\n            _stateExpirationTimeout = stateExpirationTimeout;\n            _checkInterval = checkInterval;\n        }\n\n        public void Execute(CancellationToken cancellationToken)\n        {\n            ExecuteCore(_storage, cancellationToken);\n        }\n\n        public void Execute(BackgroundProcessContext context)\n        {\n            if (context.Storage is not SqlServerStorage storage)\n            {\n                return;\n            }","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.SqlServer/ExpirationManager.cs#L41-L77","documentation":"ArgumentOutOfRangeException thrown by the ExpirationManager constructor when stateExpirationTimeout is less than TimeSpan.Zero. The background service that removes expired Hangfire records requires a non-negative grace window; a negative value is treated as a programming/config error. (Note: checkInterval has a stricter rule and must be strictly greater than zero.)","triggerScenarios":"Instantiating ExpirationManager (directly or via SqlServerStorage options that flow into it) with a negative stateExpirationTimeout TimeSpan.","commonSituations":"Computing the timeout as a difference that went negative (e.g. deadline - now when deadline already passed); reading a negative value from configuration; passing TimeSpan.FromTicks(-1) accidentally.","solutions":["Clamp the stateExpirationTimeout to TimeSpan.Zero (or a sensible positive value) before constructing ExpirationManager / SqlServerStorageOptions.","Validate config values at startup and throw a domain-specific message if negative.","Use TimeSpan.Max(TimeSpan.Zero, computed) when deriving the timeout arithmetically."],"exampleFix":"// before\nvar mgr = new ExpirationManager(storage, deadline - now, checkInterval);\n\n// after\nvar mgr = new ExpirationManager(storage, TimeSpan.Max(TimeSpan.Zero, deadline - now), checkInterval);","handlingStrategy":"validation","validationCode":"static TimeSpan AssertNonNegative(TimeSpan value, string name)\n{\n    if (value < TimeSpan.Zero)\n        throw new ArgumentOutOfRangeException(name, \"Value must be >= TimeSpan.Zero.\");\n    return value;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate time-derived config values at startup rather than letting them reach the constructor.","Use TimeSpan.Max(TimeSpan.Zero, computed) for arithmetic results.","Unit-test ExpirationManager construction with boundary values (zero, negative)."],"tags":["argument","configuration","sqlserver"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}