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

  1. Pass a positive millisecond timeout, or System.Threading.Timeout.Infinite (-1) for no timeout.
  2. Guard config-sourced values: default to a sane value (e.g. 30000 ms) when the configured timeout is <= 0.
  3. 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

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

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)