{"record":{"id":"25836bc54cc89163","repo":"JeffreySu/WeiXinMPSDK","slug":"registerfunccollection-count-value","errorCode":null,"errorMessage":"当前已有 {RegisterFuncCollection.Count} 个注册委托，不能把容量降低到 {value}。","messagePattern":"当前已有 (.+?) 个注册委托，不能把容量降低到 (.+?)。","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin/Senparc.Weixin/Containers/BaseContainer.cs","lineNumber":228,"sourceCode":"            get\n            {\n                lock (RegistrationCallbackSyncRoot)\n                {\n                    return _maximumRegistrationCallbackCount;\n                }\n            }\n            set\n            {\n                if (value <= 0)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(value), \"注册委托容量必须大于 0。\");\n                }\n\n                lock (RegistrationCallbackSyncRoot)\n                {\n                    if (value < RegisterFuncCollection.Count)\n                    {\n                        throw new InvalidOperationException($\"当前已有 {RegisterFuncCollection.Count} 个注册委托，不能把容量降低到 {value}。\");\n                    }\n\n                    _maximumRegistrationCallbackCount = value;\n                }\n            }\n        }\n\n        /// <summary>\n        /// 为 SDK 内部注册自动刷新委托，同时执行容量检查。\n        /// 保留 <see cref=\"RegisterFuncCollection\"/> 的历史类型，以兼容外部派生容器。\n        /// </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","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin/Senparc.Weixin/Containers/BaseContainer.cs#L210-L246","documentation":"The MaximumRegistrationCallbackCount setter also prevents shrinking the capacity below the number of delegates already registered. If value < RegisterFuncCollection.Count, it throws InvalidOperationException rather than silently dropping existing registrations.","triggerScenarios":"Lowering MaximumRegistrationCallbackCount on a container that already has more registered callbacks than the new value (e.g. many appIds/tokens registered, then setting the cap lower at runtime).","commonSituations":"Tightening limits in config after accounts have registered at startup; multi-tenant apps registering hundreds of appIds then a code path reducing the cap; race where registrations happen before the limit configuration runs.","solutions":["Unregister unused accounts/bags first (remove their registrations) until Count <= desired value, then set the new cap.","Set the new value to at least RegisterFuncCollection.Count, or just leave the cap unchanged.","Order initialization: set MaximumRegistrationCallbackCount before any registrations occur.","Query the current count via reflection/registration APIs or simply set a larger value if shrink is unnecessary."],"exampleFix":"// before\nMyContainer.MaximumRegistrationCallbackCount = 10; // 50 already registered -> throws\n// after\nforeach (var stale in staleAppIds) MyContainer.Remove(stale); // unregister first\nMyContainer.MaximumRegistrationCallbackCount = Math.Max(10, currentRegisteredCount);","handlingStrategy":"validation","validationCode":"var desired = 10;\n// currentCount can be tracked by your own registration bookkeeping\nif (desired < currentRegisteredCount)\n{\n    // unregister stale bags first\n    foreach (var key in staleKeys) MyContainer.Remove(key);\n}\nMyContainer.MaximumRegistrationCallbackCount = Math.Max(desired, currentRegisteredCount);","typeGuard":null,"tryCatchPattern":"try\n{\n    MyContainer.MaximumRegistrationCallbackCount = newLimit;\n}\ncatch (InvalidOperationException)\n{\n    Log(\"Too many existing registrations to shrink cap; skipping.\");\n}","preventionTips":["Set capacity limits before any registrations happen.","Track registered account count in your own registry to validate shrinks.","Unregister accounts during tenant offboarding instead of only shrinking the cap.","Keep the cap generous; shrinking it rarely helps and often fails."],"tags":["container","state","capacity","senparc-weixin"],"backgroundTag":"invalid-state-transition","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"}