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
- Ensure bag.Key is assigned before calling Update (for appid-based bags this is usually the AppId, set via Register).
- Use the container's Register method to create/register bags instead of hand-constructing and Updating them.
- If the bag is new, give it a unique Key yourself before Update.
- 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
- Prefer container Register methods over hand-built bags + Update.
- Always set Key (usually the AppId) when constructing bags manually.
- Check deserialization mappings include the Key field.
- Guard Update calls with a Key null/empty check in a shared helper.
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)