App-vNext/Polly · error · ArgumentOutOfRangeException
The ttl for items to cache must be greater than zero.
Error message
The ttl for items to cache must be greater than zero.
What it means
Thrown by the legacy Polly v7 RelativeTtl constructor when the supplied TimeSpan is less than TimeSpan.Zero. RelativeTtl is a simple ITtlStrategy that caches items for a fixed duration; a negative duration is meaningless (and would be treated as 'already expired'), so Polly rejects it with ArgumentOutOfRangeException. Note TimeSpan.Zero is allowed but produces a TTL that expires immediately.
Source
Thrown at src/Polly/Caching/RelativeTtl.cs:19
#nullable enable
namespace Polly.Caching;
/// <summary>
/// Defines a ttl strategy which will cache items for the specified time.
/// </summary>
public class RelativeTtl : ITtlStrategy
{
private readonly TimeSpan _ttl;
/// <summary>
/// Initializes a new instance of the <see cref="RelativeTtl"/> class.
/// </summary>
/// <param name="ttl">The timespan for which to consider the cache item valid.</param>
public RelativeTtl(TimeSpan ttl)
{
if (ttl < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(ttl), "The ttl for items to cache must be greater than zero.");
}
_ttl = ttl;
}
/// <summary>
/// Gets a TTL for a cacheable item, given the current execution context.
/// </summary>
/// <param name="context">The execution context.</param>
/// <param name="result">The execution result.</param>
/// <returns>A <see cref="Ttl"/> representing the remaining Ttl of the cached item.</returns>
public Ttl GetTtl(Context context, object? result) => new(_ttl);
}
View on GitHub (pinned to d0e46bdb1e)
Solutions
- Pass a non-negative TimeSpan (zero is allowed but useless; use a positive value).
- Validate/clamp the configured ttl to TimeSpan.Zero (or a sane minimum) before constructing RelativeTtl.
- If the value comes from config, default to a sensible positive ttl when the configured value is invalid.
Example fix
// before var ttl = configuredEnd - DateTime.UtcNow; // could be negative new RelativeTtl(ttl); // after var ttl = configuredEnd - DateTime.UtcNow; new RelativeTtl(ttl < TimeSpan.Zero ? TimeSpan.Zero : ttl);
Defensive patterns
Strategy: validation
Validate before calling
if (ttl < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(ttl), "ttl must be non-negative."); var strategy = new RelativeTtl(ttl);
Type guard
static bool IsTtlValid(TimeSpan ttl) => ttl >= TimeSpan.Zero;
Prevention
- Clamp any config-derived ttl to TimeSpan.Zero (or a positive minimum) before constructing RelativeTtl.
- When computing ttl as end - now, guard against now being past end.
- Validate config ttl in a startup check with a sensible default.
When it happens
Trigger: Constructing new RelativeTtl(negativeTimeSpan), or calling a Cache(...) overload that internally wraps a TimeSpan ttl in a RelativeTtl with a negative value. Subtracting two DateTimes that overflowed, or a misconfigured negative ttl from config, both produce this.
Common situations: TTL read from configuration parsed as negative; a TimeSpan computed by subtraction that went negative; accidentally passing -duration or TimeSpan.FromMilliseconds(-1).
Related errors
- The ttl for items to cache must be greater than zero.
- Value must be greater than zero.
- Value must be less than or equal to one.
- Value must be equal to or greater than {resolutionOfCircuit.
- Value must be greater than one.
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/ef52ee2662737caa.
Report an issue: GitHub.