JeffreySu/WeiXinMPSDK · error · ArgumentNullException
data
Error message
data
What it means
RequireCustomsData is a private guard used by all synchronous and asynchronous customs APIs (DeclareOrder, DeclareQuery, Redeclare). It throws ArgumentNullException named 'data' when the caller passes a null request-data object, since the library cannot build a request without it.
Solutions
- Construct the appropriate CustomsRequestData instance before calling the customs API.
- Null-check the data object at the call site before invoking.
- Fix whatever factory/configuration step is producing null instead of a data object.
Example fix
// before CustomsDeclareRequestData data = null; await tenPayV3.CustomsDeclareOrderAsync(data); // after var data = new CustomsDeclareRequestData(key, appid, mchId, mchCustomsNo, outTradeNo, ...); await tenPayV3.CustomsDeclareOrderAsync(data);
Defensive patterns
Strategy: type-guard
Validate before calling
// C#
if (data is null) throw new InvalidOperationException("Customs request data must be constructed before calling the API"); Type guard
bool IsUsable<T>(T obj) where T : class => obj is not null; // if (IsUsable(data)) await tenPayV3.CustomsDeclareOrderAsync(data);
Try / catch
try { await tenPayV3.CustomsDeclareOrderAsync(data); }
catch (ArgumentNullException ex) when (ex.ParamName == "data") { log.LogError("Customs data was null — construction failed earlier"); } Prevention
- Construct request objects inline at the call site rather than via nullable factories
- Enable nullable reference types (nullable context) so the compiler flags possible-null data
- Handle the factory's null return before invoking the API
When it happens
Trigger: Calling TenPayV3.CustomsDeclareOrder / CustomsDeclareOrderAsync / CustomsDeclareQuery / CustomsDeclareQueryAsync / CustomsRedeclare / CustomsRedeclareAsync with a null CustomsRequestDataBase instance.
Common situations: The request-data object was conditionally built (e.g. result of a factory method returning null when config was incomplete) or a variable was declared but never assigned before the API call.
Related errors
- 不能为空。
- out_trade_no、transaction_id、sub_order_no 和 sub_order_id…
- out_trade_no 和 transaction_id 至少填写一个。
- 必须指定待分账的接收方列表
- 必须指定待添加的分账接收方
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/746423810356f6d3.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPay/V3/Universal/Customs/TenPayV3.Customs.cs:122
GetCustomsUrl(CustomsRedeclarePath), data.ToXml(key), timeOut));
}
/// <summary>异步对支付订单重新进行海关申报。</summary>
public static async Task<CustomsRedeclareResult> CustomsRedeclareAsync(
CustomsRedeclareRequestData data, string key,
int timeOut = Config.TIME_OUT)
{
RequireCustomsData(data);
var xml = await PostCustomsAsync(GetCustomsUrl(CustomsRedeclarePath),
data.ToXml(key), timeOut).ConfigureAwait(false);
return new CustomsRedeclareResult(xml);
}
private static void RequireCustomsData(CustomsRequestDataBase data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
}
private static string GetCustomsUrl(string path)
{
return Senparc.Weixin.Config.TenPayV3Host.TrimEnd('/') + path;
}
private static string PostCustoms(string url, string xml, int timeOut)
{
var bytes = Encoding.UTF8.GetBytes(xml);
using (var stream = new MemoryStream(bytes))
{
return RequestUtility.HttpPost(CommonDI.CommonSP, url, null,
stream, timeOut: timeOut);
}
}
View on GitHub (pinned to be573f6f94)