dotnet/aspnetcore · error · ArgumentOutOfRangeException

The sliding expiration value must be positive.

Error message

The sliding expiration value must be positive.

What it means

Thrown in the SqlServerCache constructor when DefaultSlidingExpiration is <= TimeSpan.Zero. The default sliding expiration is the fallback lifetime applied to entries that do not specify their own expiration, so it must be a positive duration.

Solutions

  1. Set DefaultSlidingExpiration to a positive TimeSpan (e.g. TimeSpan.FromMinutes(20)) in AddDistributedSqlServerCache.
  2. If binding from IConfiguration, ensure the config key maps to a valid duration string.
  3. Validate the value at startup and fail fast with a clear message before cache use.

Example fix

// before: unset default sliding expiration resolves to zero
services.AddDistributedSqlServerCache(o => {
    o.ConnectionString = cs; o.SchemaName = "dbo"; o.TableName = "Cache";
});

// after: positive default
services.AddDistributedSqlServerCache(o => {
    o.ConnectionString = cs; o.SchemaName = "dbo"; o.TableName = "Cache";
    o.DefaultSlidingExpiration = TimeSpan.FromMinutes(20);
});
Defensive patterns

Strategy: validation

Validate before calling

if (options.DefaultSlidingExpiration <= TimeSpan.Zero) { /* set a positive default before building the cache */ }

Prevention

When it happens

Trigger: Configuring SqlServerCache with options.DefaultSlidingExpiration <= TimeSpan.Zero (zero, negative, or unset default that resolves to zero).

Common situations: Forgetting to set DefaultSlidingExpiration in AddDistributedSqlServerCache (when it defaults to TimeSpan.Zero); misconfiguring via a config binding that produced zero; passing a negative value by mistake.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/fddbfa104d26e955. Report an issue: GitHub.

Appendix: source

Thrown at src/Caching/SqlServer/src/SqlServerCache.cs:54

    public SqlServerCache(IOptions<SqlServerCacheOptions> options)
    {
        var cacheOptions = options.Value;

        ArgumentThrowHelper.ThrowIfNullOrEmpty(cacheOptions.ConnectionString);
        ArgumentThrowHelper.ThrowIfNullOrEmpty(cacheOptions.SchemaName);
        ArgumentThrowHelper.ThrowIfNullOrEmpty(cacheOptions.TableName);

        if (cacheOptions.ExpiredItemsDeletionInterval.HasValue &&
            cacheOptions.ExpiredItemsDeletionInterval.Value < MinimumExpiredItemsDeletionInterval)
        {
            throw new ArgumentException(
                $"{nameof(SqlServerCacheOptions.ExpiredItemsDeletionInterval)} cannot be less than the minimum " +
                $"value of {MinimumExpiredItemsDeletionInterval.TotalMinutes} minutes.");
        }
        if (cacheOptions.DefaultSlidingExpiration <= TimeSpan.Zero)
        {
#pragma warning disable CA2208 // Instantiate argument exceptions correctly
            throw new ArgumentOutOfRangeException(
                nameof(cacheOptions.DefaultSlidingExpiration),
                cacheOptions.DefaultSlidingExpiration,
                "The sliding expiration value must be positive.");
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
        }

        _systemClock = cacheOptions.SystemClock ?? new SystemClock();
        _expiredItemsDeletionInterval =
            cacheOptions.ExpiredItemsDeletionInterval ?? DefaultExpiredItemsDeletionInterval;
        _deleteExpiredCachedItemsDelegate = DeleteExpiredCacheItems;
        _defaultSlidingExpiration = cacheOptions.DefaultSlidingExpiration;

        _dbOperations = new DatabaseOperations(
            cacheOptions.ConnectionString,
            cacheOptions.SchemaName,
            cacheOptions.TableName,
            _systemClock);
    }

View on GitHub (pinned to 3600ca084e)