dotnet/efcore · error · ArgumentException
Timeout must be greater than or equal to zero. Provided time
Error message
Timeout must be greater than or equal to zero. Provided timeout: {seconds} seconds. What it means
Thrown by SetCommandTimeout(TimeSpan) when the supplied timeout is negative (and not Timeout.InfiniteTimeSpan, which maps to 0). Command timeouts must be >= 0 seconds; the underlying ADO.NET DbCommand.CommandTimeout rejects negatives.
Source
Thrown at src/EFCore.Relational/Extensions/RelationalDatabaseFacadeExtensions.cs:967
/// <see cref="SetCommandTimeout(DatabaseFacade,int?)" />.
/// </para>
/// <para>
/// See <see href="https://aka.ms/efcore-docs-connections">Connections and connection strings</see> for more information and examples.
/// </para>
/// </remarks>
/// <param name="databaseFacade">The <see cref="DatabaseFacade" /> for the context.</param>
/// <param name="timeout">The timeout to use.</param>
public static void SetCommandTimeout(this DatabaseFacade databaseFacade, TimeSpan timeout)
{
if (timeout == Timeout.InfiniteTimeSpan)
{
databaseFacade.SetCommandTimeout(0);
return;
}
if (timeout < TimeSpan.Zero)
{
throw new ArgumentException(RelationalStrings.TimeoutTooSmall(timeout.TotalSeconds));
}
if (timeout.TotalSeconds > int.MaxValue)
{
throw new ArgumentException(RelationalStrings.TimeoutTooBig(timeout.TotalSeconds));
}
databaseFacade.SetCommandTimeout(Convert.ToInt32(timeout.TotalSeconds));
}
/// <summary>
/// Returns the timeout (in seconds) set for commands executed with this <see cref="DbContext" />.
/// </summary>
/// <remarks>
/// <para>
/// Note that the command timeout is distinct from the connection timeout, which is commonly
/// set on the database connection string.
/// </para>View on GitHub (pinned to dbf9771522)
Solutions
- Pass Timeout.InfiniteTimeSpan for no timeout, or a non-negative TimeSpan.
- Clamp the configured value to >= 0 before calling SetCommandTimeout: TimeSpan.FromSeconds(Math.Max(0, seconds)).
- Validate configuration at startup and fail fast with a clear message instead of at query time.
Example fix
// before
db.Database.SetCommandTimeout(TimeSpan.FromSeconds(cfg.CommandTimeout)); // cfg.CommandTimeout = -5
// after
var seconds = Math.Max(0, cfg.CommandTimeout);
db.Database.SetCommandTimeout(seconds == 0
? Timeout.InfiniteTimeSpan
: TimeSpan.FromSeconds(seconds)); Defensive patterns
Strategy: validation
Validate before calling
if (timeout < TimeSpan.Zero && timeout != Timeout.InfiniteTimeSpan)
throw new ArgumentOutOfRangeException(nameof(timeout));
db.Database.SetCommandTimeout(timeout); Type guard
static bool IsValidTimeout(TimeSpan t)
=> t == Timeout.InfiniteTimeSpan || (t >= TimeSpan.Zero && t.TotalSeconds <= int.MaxValue); Prevention
- Clamp configuration values to >= 0 before passing.
- Use Timeout.InfiniteTimeSpan for no timeout, never a negative span.
- Validate timeout settings at startup.
When it happens
Trigger: Calling db.Database.SetCommandTimeout(negativeTimeSpan) (RelationalDatabaseFacadeExtensions.cs:965-967). Happens when a TimeSpan is computed from a misconfigured setting or arithmetic that underflows.
Common situations: Reading timeout from configuration that is unset/default -1; subtracting durations producing a negative; passing -1 seconds expecting infinite (use Timeout.InfiniteTimeSpan instead); misparsed int values.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timeout must be less than or equal to Int32.MaxValue (214748
- The container with the name '{containerName}' does not exist
- Unable to find expected assembly attribute [DesignTimeProvid
- A migration name must be specified.
- The migration name '{name}' is not valid. Migration names ca
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/ecaa5c0887505dc8.
Report an issue: GitHub.