HangfireIO/Hangfire · error · ArgumentException
Timeout argument value should be greater than zero.
Error message
Timeout argument value should be greater than zero.
What it means
DisableConcurrentExecutionAttribute's constructor (DisableConcurrentExecutionAttribute.cs:30) validates that the timeout (in seconds) is non-negative. A negative timeout is meaningless for a distributed lock acquisition and would produce invalid TimeSpan behavior, so an ArgumentException is thrown. Note: the message says 'greater than zero' but the check is '< 0', so 0 is permitted (meaning no wait / immediate fail).
Source
Thrown at src/Hangfire.Core/DisableConcurrentExecutionAttribute.cs:30
//
// You should have received a copy of the GNU Lesser General Public
// License along with Hangfire. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Globalization;
using System.Linq;
using Hangfire.Annotations;
using Hangfire.Common;
using Hangfire.Server;
using Newtonsoft.Json;
namespace Hangfire
{
public class DisableConcurrentExecutionAttribute : JobFilterAttribute, IServerFilter
{
public DisableConcurrentExecutionAttribute(int timeoutInSeconds)
{
if (timeoutInSeconds < 0) throw new ArgumentException("Timeout argument value should be greater than zero.");
TimeoutSec = timeoutInSeconds;
}
[JsonConstructor]
public DisableConcurrentExecutionAttribute(string resource, int timeoutSec)
: this(timeoutSec)
{
Resource = resource;
}
[CanBeNull]
public string Resource { get; }
public int TimeoutSec { get; }
public void OnPerforming(PerformingContext context)
{
var resource = GetResource(context.BackgroundJob.Job);View on GitHub (pinned to c236dd0f93)
Solutions
- Use a non-negative timeout value (>= 0).
- Validate configuration-sourced timeout values before applying the attribute.
- Use a meaningful positive timeout (e.g. 30 or 60 seconds) to allow reasonable wait time for the lock.
Example fix
// before
[DisableConcurrentExecution(-5)]
public void ProcessJob(int id) { ... }
// after
[DisableConcurrentExecution(30)]
public void ProcessJob(int id) { ... } Defensive patterns
Strategy: validation
Validate before calling
if (timeoutInSeconds < 0)
throw new ArgumentOutOfRangeException(nameof(timeoutInSeconds),
"Timeout must be non-negative.");
// then apply attribute or configure dynamically Prevention
- Use non-negative timeout values for DisableConcurrentExecutionAttribute.
- Validate config-sourced timeout values before applying.
- Prefer a positive timeout (e.g. 30s) to allow reasonable lock wait time.
When it happens
Trigger: Applying [DisableConcurrentExecution(timeoutInSeconds)] with a negative value, e.g. [DisableConcurrentExecution(-1)].
Common situations: Config-driven timeout value parsed as negative due to a sign error or missing config default; arithmetic that subtracts producing a negative result.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Can not release a distributed lock: it was not acquired.
- Unable to obtain resource identifier: {ex.Message}
- Could not release a lock on the resource '{lockCommand.Item3
- Attempts value must be equal or greater than zero.
- DelaysInSeconds value must be an array of non-negative numbe
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/2addffcaaa33b911.
Report an issue: GitHub.