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

  1. Pass an actual IWeixinCredentialProvider implementation (custom or library-supplied) to the call.
  2. Register your provider in the DI container (services.AddSingleton<IWeixinCredentialProvider, MyProvider>()) and inject it instead of newing up.
  3. 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

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


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)