{"record":{"id":"9c6dd09a6ab92c42","repo":"JeffreySu/WeiXinMPSDK","slug":"maximumregistrationcallbackcount","errorCode":null,"errorMessage":"注册委托数量已达到上限 {_maximumRegistrationCallbackCount}，请先注销不再使用的账号或提高 MaximumRegistrationCallbackCount。","messagePattern":"注册委托数量已达到上限 (.+?)，请先注销不再使用的账号或提高 MaximumRegistrationCallbackCount。","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin/Senparc.Weixin/Containers/BaseContainer.cs","lineNumber":257,"sourceCode":"        /// </summary>\n        protected static void SetRegistrationCallback(string shortKey, Func<Task<TBag>> registerFunc)\n        {\n            if (shortKey == null)\n            {\n                throw new ArgumentNullException(nameof(shortKey));\n            }\n\n            if (registerFunc == null)\n            {\n                throw new ArgumentNullException(nameof(registerFunc));\n            }\n\n            lock (RegistrationCallbackSyncRoot)\n            {\n                if (!RegisterFuncCollection.ContainsKey(shortKey) &&\n                    RegisterFuncCollection.Count >= _maximumRegistrationCallbackCount)\n                {\n                    throw new InvalidOperationException(\n                        $\"注册委托数量已达到上限 {_maximumRegistrationCallbackCount}，请先注销不再使用的账号或提高 MaximumRegistrationCallbackCount。\");\n                }\n\n                RegisterFuncCollection[shortKey] = registerFunc;\n            }\n        }\n\n        /// <summary>注销指定账号，同时移除自动重注册委托和缓存项。</summary>\n        public static bool Unregister(string shortKey)\n        {\n            if (shortKey == null)\n            {\n                throw new ArgumentNullException(nameof(shortKey));\n            }\n\n            var callbackRemoved = RegisterFuncCollection.TryRemove(shortKey, out _);\n            RemoveFromCache(shortKey);\n            return callbackRemoved;","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin/Senparc.Weixin/Containers/BaseContainer.cs#L239-L275","documentation":"SetRegistrationCallback stores one callback per bag keyed by shortKey. When registering a NEW key while RegisterFuncCollection.Count already equals _maximumRegistrationCallbackCount, it throws InvalidOperationException, telling you to unregister stale accounts or raise the limit.","triggerScenarios":"Registering more distinct accounts/appIds (each triggering SetRegistrationCallback with a new shortKey) than MaximumRegistrationCallbackCount allows; happens inside container registration (e.g. AccessTokenContainer.Register) once the cap is hit.","commonSituations":"Multi-tenant systems onboarding more WeChat accounts than the default cap; long-running services accumulating registrations without cleanup; defaults too low after migrating many tenants.","solutions":["Increase the container's MaximumRegistrationCallbackCount before registering (set it to expected account count with headroom).","Remove/unregister bags for accounts no longer in use to free slots.","Audit for duplicate registrations of the same appId that consume slots unnecessarily.","If you genuinely need unbounded accounts, set the cap high enough at startup (it must exceed total registrations)."],"exampleFix":"// before\nAccessTokenContainer.Register(appId, secret); // throws when cap reached\n// after\nif (expectedAccounts > currentCap)\n{\n    AccessTokenContainer.MaximumRegistrationCallbackCount = expectedAccounts * 2;\n}\nAccessTokenContainer.Register(appId, secret);","handlingStrategy":"try-catch","validationCode":"// before registering, ensure capacity\nif (expectedAccounts >= configuredCap)\n    MyContainer.MaximumRegistrationCallbackCount = expectedAccounts * 2;","typeGuard":null,"tryCatchPattern":"try\n{\n    AccessTokenContainer.Register(appId, secret);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"上限\"))\n{\n    Log(\"Registration cap reached; raising limit and retrying.\");\n    AccessTokenContainer.MaximumRegistrationCallbackCount *= 2;\n    AccessTokenContainer.Register(appId, secret);\n}","preventionTips":["Size MaximumRegistrationCallbackCount to total tenants plus headroom at startup.","Unregister bags when tenants are removed to free slots.","Alert when the number of registered accounts approaches the cap.","Avoid re-registering the same appId repeatedly."],"tags":["container","capacity","limit-exceeded","multi-tenant"],"backgroundTag":"rate-limit-exceeded","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"}