JeffreySu/WeiXinMPSDK · error · ArgumentNullException
credentialProvider
Error message
credentialProvider
What it means
AccessTokenContainer.RegisterWithCredentialProviderAsync throws ArgumentNullException with parameter name "credentialProvider" when the IWeixinCredentialProvider instance is null. The provider is required because it supplies the corp secret via GetSecretAsync; registering without it cannot produce a token bag. The check happens after the string validations and before RegisterCoreAsync runs.
Solutions
- Pass an actual IWeixinCredentialProvider implementation (custom or library-supplied) to the call.
- Register your provider in the DI container (services.AddSingleton<IWeixinCredentialProvider, MyProvider>()) and inject it instead of newing up.
- If resolved dynamically, assert non-null with a clear startup error before calling Register.
Example fix
// before await AccessTokenContainer.RegisterWithCredentialProviderAsync(regKey, corpId, provider); // provider null (DI miss) // after services.AddSingleton<IWeixinCredentialProvider, ConfigCredentialProvider>(); var provider = serviceProvider.GetRequiredService<IWeixinCredentialProvider>(); await AccessTokenContainer.RegisterWithCredentialProviderAsync(regKey, corpId, provider);
Defensive patterns
Strategy: validation
Validate before calling
if (provider is null)
throw new InvalidOperationException("IWeixinCredentialProvider not registered in DI.");
await AccessTokenContainer.RegisterWithCredentialProviderAsync(regKey, corpId, provider); Type guard
bool HasProvider(IWeixinCredentialProvider? p) => p is not null;
Try / catch
try
{
await AccessTokenContainer.RegisterWithCredentialProviderAsync(regKey, corpId, provider);
}
catch (ArgumentNullException ex) when (ex.ParamName == "credentialProvider")
{
log.LogCritical("Credential provider is null; check DI registrations.");
throw;
} Prevention
- Always resolve the provider via DI GetRequiredService so a missing registration fails with a clear message.
- Add an integration test that boots the app and performs token registration once.
- Avoid optional provider properties that default to null.
When it happens
Trigger: Calling RegisterWithCredentialProviderAsync(regKey, corpId, null) — e.g. DI failed to resolve IWeixinCredentialProvider, or a manual construction passed null.
Common situations: Missing DI registration for the credential provider implementation so the injected parameter is null; conditional wiring in tests that skipped the provider; property not initialized before use.
Related errors
- brandApiCredentials
- ArgumentNullException (destination is null)
- ArgumentNullException (options is null)
- operation
- 凭据提供器返回了空 CorpSecret。
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/be1df100a78675f5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.Work/Senparc.Weixin.Work/Containers/AccessTokenContainer.cs:394
string registrationKey,
string corpId,
IWeixinCredentialProvider credentialProvider,
string name = null,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(registrationKey))
{
throw new ArgumentException("registrationKey 不能为空。", nameof(registrationKey));
}
if (string.IsNullOrWhiteSpace(corpId))
{
throw new ArgumentException("CorpId 不能为空。", nameof(corpId));
}
if (credentialProvider == null)
{
throw new ArgumentNullException(nameof(credentialProvider));
}
async Task<AccessTokenBag> RegisterCoreAsync(CancellationToken token)
{
var secret = await credentialProvider.GetSecretAsync(registrationKey, token).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(secret))
{
throw new InvalidOperationException("凭据提供器返回了空 CorpSecret。");
}
var bag = new AccessTokenBag
{
Name = name,
CorpId = corpId,
CorpSecret = secret,
ExpireTime = DateTimeOffset.MinValue,
AccessTokenResult = new AccessTokenResult()
};View on GitHub (pinned to be573f6f94)