{"record":{"id":"e6b0ced65a007676","repo":"JeffreySu/WeiXinMPSDK","slug":"registrationkey","errorCode":null,"errorMessage":"registrationKey 不能为空。","messagePattern":"registrationKey 不能为空。","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/Containers/AccessTokenContainer.cs","lineNumber":384,"sourceCode":"            var registerProviderTask = ProviderTokenContainer.RegisterAsync(corpId, corpSecret);//连带注册ProviderTokenContainer\n\n            await Task.WhenAll(new[] { registerTask, registerJsApiTask, registerProviderTask }).ConfigureAwait(false);//等待所有任务完成\n        }\n\n        /// <summary>\n        /// 使用稳定 registrationKey 和外部凭据提供器注册企业微信 AccessToken。\n        /// 自动重注册委托不捕获明文 CorpSecret；调用 API 时使用返回的 registrationKey 作为 AppKey。\n        /// </summary>\n        public static async Task RegisterWithCredentialProviderAsync(\n            string registrationKey,\n            string corpId,\n            IWeixinCredentialProvider credentialProvider,\n            string name = null,\n            CancellationToken cancellationToken = default)\n        {\n            if (string.IsNullOrWhiteSpace(registrationKey))\n            {\n                throw new ArgumentException(\"registrationKey 不能为空。\", nameof(registrationKey));\n            }\n\n            if (string.IsNullOrWhiteSpace(corpId))\n            {\n                throw new ArgumentException(\"CorpId 不能为空。\", nameof(corpId));\n            }\n\n            if (credentialProvider == null)\n            {\n                throw new ArgumentNullException(nameof(credentialProvider));\n            }\n\n            async Task<AccessTokenBag> RegisterCoreAsync(CancellationToken token)\n            {\n                var secret = await credentialProvider.GetSecretAsync(registrationKey, token).ConfigureAwait(false);\n                if (string.IsNullOrWhiteSpace(secret))\n                {\n                    throw new InvalidOperationException(\"凭据提供器返回了空 CorpSecret。\");","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/Containers/AccessTokenContainer.cs#L366-L402","documentation":"AccessTokenContainer.RegisterWithCredentialProviderAsync throws ArgumentException(\"registrationKey 不能为空。\") when the registrationKey argument is null, empty, or whitespace. The registrationKey is the lookup key used to fetch the corp secret from the IWeixinCredentialProvider, so it must be supplied. This is an argument validation guard executed before any other checks.","triggerScenarios":"Calling RegisterWithCredentialProviderAsync(null, corpId, provider, ...) or passing \"\" / \"  \" as registrationKey — e.g. reading the key from config that is missing or blank.","commonSituations":"Config/环境 variables not set so the key resolves to empty; copying sample code and leaving the key placeholder empty; binding errors in DI that yield empty strings instead of null.","solutions":["Pass the actual registration key registered in your credential provider, e.g. await AccessTokenContainer.RegisterWithCredentialProviderAsync(\"myCorpSecretKey\", corpId, provider);","If the key comes from configuration, validate it with string.IsNullOrWhiteSpace before calling and fail startup with a clear message.","Ensure registrationKey matches the key used when registering secrets with the provider."],"exampleFix":"// before\nawait AccessTokenContainer.RegisterWithCredentialProviderAsync(config.RegKey, corpId, provider); // RegKey = \"\"\n// after\nif (string.IsNullOrWhiteSpace(config.RegKey)) throw new InvalidOperationException(\"RegKey missing in config.\");\nawait AccessTokenContainer.RegisterWithCredentialProviderAsync(config.RegKey, corpId, provider);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(registrationKey))\n    throw new InvalidOperationException(\"registrationKey is not configured; check appsettings/env.\");\nawait AccessTokenContainer.RegisterWithCredentialProviderAsync(registrationKey, corpId, provider);","typeGuard":"bool IsValidRegistrationKey(string key) => !string.IsNullOrWhiteSpace(key);","tryCatchPattern":"try\n{\n    await AccessTokenContainer.RegisterWithCredentialProviderAsync(regKey, corpId, provider);\n}\ncatch (ArgumentException ex) when (ex.ParamName == \"registrationKey\")\n{\n    log.LogCritical(\"Registration key is empty; fix configuration and restart.\");\n    throw;\n}","preventionTips":["Validate all WeChat Work credentials at application startup with fail-fast checks.","Keep registrationKey values in typed config classes validated on bind.","Use distinct, descriptive keys per environment to avoid blank placeholders."],"tags":["argument-validation","registration","access-token"],"backgroundTag":"empty-required-field","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}