JeffreySu/WeiXinMPSDK · error · WeixinException

ContainerBag 更新时,Key 不能为空!类型:

Error message

ContainerBag 更新时,Key 不能为空!类型:

What it means

BaseContainer.Update(TBag bag, TimeSpan? expiry) requires the bag's Key to be non-empty, because it delegates to Update(bag.Key, bag, expiry). A bag with a null/empty Key cannot be located in the container, so a WeixinException is thrown to surface the misconfigured bag and its type.

Solutions

  1. Ensure bag.Key is assigned before calling Update (for appid-based bags this is usually the AppId, set via Register).
  2. Use the container's Register method to create/register bags instead of hand-constructing and Updating them.
  3. If the bag is new, give it a unique Key yourself before Update.
  4. Check TBag subclasses/custom bags for Key initialization bugs and add a null-check/constructor requirement for Key.

Example fix

// before
var bag = new AccessTokenBag();
BaseContainer<AccessTokenBag>.Update(bag, null); // Key is null -> throws
// after
AccessTokenContainer.Register(appId, appSecret); // recommended: creates a keyed bag
// or, if manual:
var bag = new AccessTokenBag { Key = appId, AppId = appId };
BaseContainer<AccessTokenBag>.Update(bag, null);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(bag.Key))
    throw new InvalidOperationException($"{bag.GetType().Name}.Key must be set before Update.");
BaseContainer<TBag>.Update(bag, expiry);

Type guard

bool IsUpdatable<TBag>(TBag bag) where TBag : IBaseContainerBag =>
    bag != null && !string.IsNullOrEmpty(bag.Key);

Try / catch

try
{
    BaseContainer<TBag>.Update(bag, expiry);
}
catch (WeixinException ex)
{
    Log($"Bag without Key: {ex.Message}");
    // register properly or assign Key, then retry
}

Prevention

When it happens

Trigger: Constructing a new TBag and calling Update without ever assigning bag.Key (or without registering the bag so Key gets set); a bag whose Key assignment was skipped due to a failed property initializer; passing a deserialized bag where Key wasn't populated.

Common situations: Manually creating container bags (e.g. new AccessTokenBag/JsApiTicketBag) and pushing them via Update instead of going through Register; custom TBag subclasses overriding Key improperly; JSON deserialization dropping the Key field.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Senparc.Weixin/Senparc.Weixin/Containers/BaseContainer.cs:476

                //var c2 = ItemCollection.GetCount();
            }
            //var containerCacheKey = GetContainerCacheKey();

            bag.CacheTime = SystemTime.Now;

            Cache.Update(cacheKey, bag, expiry);//更新到缓存,TODO:有的缓存框架可一直更新Hash中的某个键值对
        }

        /// <summary>
        /// 更新已经添加过的数据项
        /// </summary>
        /// <param name="bag">为null时删除该项</param>
        /// <param name="expiry"></param>
        public static void Update(TBag bag, TimeSpan? expiry)
        {
            if (string.IsNullOrEmpty(bag.Key))
            {
                throw new WeixinException("ContainerBag 更新时,Key 不能为空!类型:" + bag.GetType());
            }

            Update(bag.Key, bag, expiry);
        }

        /// <summary>
        /// 更新数据项(本地缓存不会改变原有值的 HashCode)
        /// </summary>
        /// <param name="shortKey"></param>
        /// <param name="partialUpdate">为null时删除该项</param>
        /// <param name="expiry"></param>
        public static void Update(string shortKey, Action<TBag> partialUpdate, TimeSpan? expiry)
        {
            var cacheKey = GetBagCacheKey(shortKey);
            if (partialUpdate == null)
            {
                Cache.RemoveFromCache(cacheKey);//移除对象
            }

View on GitHub (pinned to be573f6f94)