JeffreySu/WeiXinMPSDK · error · UnRegisterAppIdException

此wxOpenAppId(…

Error message

此wxOpenAppId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!

What it means

AccessTokenContainer.GetAccessTokenResult throws UnRegisterAppIdException when the given wxOpenAppId has not been registered via AccessTokenContainer.Register. The SDK stores access tokens in a container keyed by AppId; requesting a token for an unregistered AppId is treated as a configuration error, not an API error.

Solutions

  1. Call AccessTokenContainer.Register(wxOpenAppId, wxOpenAppSecret) once during application startup
  2. Ensure the registered AppId string exactly matches the one requested (no typos/casing)
  3. Use Config.SenparcWeixinSetting bindings so Register and consumers read the same settings
  4. Verify Register actually runs on every deployment/instance (global.asax/Startup), not conditionally

Example fix

// before
var token = AccessTokenContainer.GetAccessTokenResult(appId); // appId never registered
// after
// Startup:
AccessTokenContainer.Register(appId, appSecret, "MiniProgram");
// Usage:
var token = AccessTokenContainer.GetAccessTokenResult(appId);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!AccessTokenContainer.CheckRegistered(wxOpenAppId)) AccessTokenContainer.Register(wxOpenAppId, appSecret);

Try / catch

try { return AccessTokenContainer.GetAccessTokenResult(appId); }
catch (UnRegisterAppIdException ex) { logger.LogError(ex, "AppId {AppId} not registered — call AccessTokenContainer.Register at startup", appId); throw; }

Prevention

When it happens

Trigger: Calling GetAccessTokenResult/GetAccessToken (or any API relying on it) with an AppId that was never passed to AccessTokenContainer.Register(appId, appSecret) at application startup, or after a cache flush/restart that lost registration state.

Common situations: Multiple Mini Programs configured but only some registered; Register call placed in a code path that never executes (e.g. guarded by environment check); scaled-out instances where only one instance ran the registration; AppId typo mismatch between Register and the consumer.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/63763b2f57711253. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.WxOpen/src/Senparc.Weixin.WxOpen/Senparc.Weixin.WxOpen/Containers/AccessTokenContainer.cs:130

        /// <param name="wxOpenAppId"></param>
        /// <param name="getNewToken">是否强制重新获取新的Token</param>
        /// <returns></returns>
        public static string GetAccessToken(string wxOpenAppId, bool getNewToken = false)
        {
            return GetAccessTokenResult(wxOpenAppId, getNewToken).access_token;
        }

        /// <summary>
        /// 获取可用AccessTokenResult对象
        /// </summary>
        /// <param name="wxOpenAppId"></param>
        /// <param name="getNewToken">是否强制重新获取新的Token</param>
        /// <returns></returns>
        public static AccessTokenResult GetAccessTokenResult(string wxOpenAppId, bool getNewToken = false)
        {
            if (!CheckRegistered(wxOpenAppId))
            {
                throw new UnRegisterAppIdException(wxOpenAppId, string.Format("此wxOpenAppId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!", wxOpenAppId));
            }

            var accessTokenBag = TryGetItem(wxOpenAppId);

            using (Cache.BeginCacheLock(LockResourceName, wxOpenAppId))//同步锁
            {
                accessTokenBag = TryGetItem(wxOpenAppId);//获锁后重新读取,避免使用分布式缓存中的旧副本重复刷新
                if (getNewToken || accessTokenBag.AccessTokenExpireTime <= SystemTime.Now)
                {
                    //已过期,重新获取
                    accessTokenBag.AccessTokenResult = CommonApi.GetToken(accessTokenBag.WxOpenAppId, accessTokenBag.WxOpenAppSecret);
                    accessTokenBag.AccessTokenExpireTime = ApiUtility.GetExpireTime(accessTokenBag.AccessTokenResult.expires_in);
                    Update(accessTokenBag, null);//更新到缓存
                }
            }
            return accessTokenBag.AccessTokenResult;
        }

View on GitHub (pinned to be573f6f94)