HangfireIO/Hangfire · error · ArgumentOutOfRangeException
Attempts value must be equal or greater than zero.
Error message
Attempts value must be equal or greater than zero.
What it means
The Attempts property on AutomaticRetryAttribute (and other retry attributes that reuse it) represents the maximum automatic retry count and must be non-negative. Setting it to a negative number throws ArgumentOutOfRangeException immediately at assignment time, before any job runs. This is input validation on a configuration property, not a runtime job-execution failure.
Source
Thrown at src/Hangfire.Core/AutomaticRetryAttribute.cs:131
DelayInSecondsByAttemptFunc = DefaultDelayInSecondsByAttemptFunc;
LogEvents = true;
OnAttemptsExceeded = AttemptsExceededAction.Fail;
Order = 20;
}
/// <summary>
/// Gets or sets the maximum number of automatic retry attempts.
/// </summary>
/// <value>Any non-negative number.</value>
/// <exception cref="ArgumentOutOfRangeException">The value in a set operation is less than zero.</exception>
public int Attempts
{
get { lock (_lockObject) { return _attempts; } }
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value), @"Attempts value must be equal or greater than zero.");
}
lock (_lockObject)
{
_attempts = value;
}
}
}
/// <summary>
/// Gets or sets the delays between attempts.
/// </summary>
/// <value>An array of non-negative numbers.</value>
/// <exception cref="ArgumentNullException">The value in a set operation is null.</exception>
/// <exception cref="ArgumentException">The value contain one or more negative numbers.</exception>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int[] DelaysInSeconds
{View on GitHub (pinned to c236dd0f93)
Solutions
- Set Attempts to 0 to disable retries, or a positive integer for the number of attempts.
- If you intended infinite retries, that is not supported — use a large finite number or implement a custom retry filter.
- Validate config-driven values before assigning: clamp negatives to 0 in your configuration loader.
Example fix
// before
[AutomaticRetry(Attempts = -1)]
public void Run() { }
// after
[AutomaticRetry(Attempts = 0)] // disable retries
public void Run() { } Defensive patterns
Strategy: validation
Validate before calling
int attempts = LoadFromConfig(); if (attempts < 0) attempts = 0; // clamp before assigning attribute.Attempts = attempts;
Type guard
static bool IsValidAttempts(int value) => value >= 0;
Prevention
- Validate config-derived values before assigning to Attempts.
- Use 0 to disable retries; never use negatives.
- Add a unit test asserting Attempts assignment accepts 0 and rejects -1.
When it happens
Trigger: Setting [AutomaticRetry(Attempts = -1)] (or assigning Attempts = -5) on a job method or globally via GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = -1 }). Any value < 0 triggers the guard.
Common situations: Misunderstanding Attempts as a retry count offset (setting -1 intending 'infinite' or 'none'); loading Attempts from configuration that parses an empty/invalid string to a negative; copying a value meant for DelaysInSeconds.
Related errors
- DelaysInSeconds value must be an array of non-negative numbe
- WorkerCount property value should be positive.
- StopTimeout must be either equal to or less than {Int32.MaxV
- ShutdownTimeout must be either equal to or less than {Int32.
- SchedulePollingInterval must be non-negative and either equa
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/62dd873198f99b1f.
Report an issue: GitHub.