JeffreySu/WeiXinMPSDK · error · ArgumentOutOfRangeException
超时时间必须大于 0,或使用 Timeout.Infinite。
Error message
超时时间必须大于 0,或使用 Timeout.Infinite。
What it means
SendAsync validates the timeOut parameter before issuing the HTTP request: it must be strictly greater than 0 or exactly Timeout.Infinite (-1). Any other value (0, negative other than -1) causes ArgumentOutOfRangeException naming timeOut.
Solutions
- Pass a positive millisecond timeout, or System.Threading.Timeout.Infinite (-1) for no timeout.
- Guard config-sourced values: default to a sane value (e.g. 30000 ms) when the configured timeout is <= 0.
- Check the caller that computes the timeout to ensure the unit conversion yields milliseconds > 0.
Example fix
// before await client.SendAsync(requestMethod, url, timeOut: 0); // after await client.SendAsync(requestMethod, url, timeOut: 30_000); // or Timeout.Infinite
Defensive patterns
Strategy: validation
Validate before calling
if (timeOut <= 0 && timeOut != Timeout.Infinite)
timeOut = 30_000; // sane default before calling SendAsync Try / catch
try { await client.SendAsync(method, url, timeOut); }
catch (ArgumentOutOfRangeException) { logger.LogError("Invalid timeout {TimeOut}", timeOut); } Prevention
- Centralize timeout constants; never pass 0 to mean 'no timeout' — use Timeout.Infinite.
- Clamp config-sourced timeouts to a minimum positive value.
- Watch unit conversions (seconds vs milliseconds).
When it happens
Trigger: Calling SendAsync (or any wrapper such as SendAsync that forwards a timeout) with timeOut = 0, a negative value like -1000, or an uninitialized/zero default from calling code.
Common situations: Passing 0 meaning 'no timeout' (wrong assumption); reading a timeout from config where the key is missing so the value defaults to 0; computing a timeout that evaluates to 0 after conversion of seconds/minutes.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/d1d2742e3aa5124c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/TenPayHttpClient/TenPayHttpClient.cs:157
}
public Task<T> SendAsync<T>(string url, object data, int timeOut = Senparc.Weixin.Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkSign = true, Func<T> createDefaultInstance = null)
where T : ReturnJsonBase/*, new()*/
{
return SendAsync(url, data, CancellationToken.None, timeOut, requestMethod, checkSign, createDefaultInstance);
}
public async Task<T> SendAsync<T>(string url, object data, CancellationToken cancellationToken, int timeOut = Senparc.Weixin.Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkSign = true, Func<T> createDefaultInstance = null)
where T : ReturnJsonBase/*, new()*/
{
T result = null;
HttpMethod method = GetHttpMethod(requestMethod);
try
{
if (timeOut <= 0 && timeOut != Timeout.Infinite)
{
throw new ArgumentOutOfRangeException(nameof(timeOut), "超时时间必须大于 0,或使用 Timeout.Infinite。 ");
}
using var request = new HttpRequestMessage(method, url);
SetRequestHeaders(request);
//设置请求 Json 字符串
string jsonString = data != null
? data.ToJson(false, RequestJsonSerializerSettings)
: "";
WeixinTrace.SendApiPostDataLog(url, jsonString); //记录Post的Json数据
request.Content = new StringContent(jsonString, Encoding.UTF8, mediaType: "application/json");
// 进行签名
var authorization = await GenerateAuthorizationHeader(request);
request.Headers.Add("Authorization", $"WECHATPAY2-{_signer.GetAlgorithm()} {authorization}");
// 发送请求
using var timeoutCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);View on GitHub (pinned to be573f6f94)