JeffreySu/WeiXinMPSDK · error · WeixinMenuException

单击按钮的key不能为空!

Error message

单击按钮的key不能为空!

What it means

When deserializing a Weixin menu response, GetButtonGroup requires a bottom-level button of type CLICK to carry a non-empty key. A null/missing type or a CLICK button with an empty key throws WeixinMenuException '单击按钮的key不能为空!'.

Solutions

  1. Open the Weixin admin console and set a key for every CLICK-type button
  2. Update the menu via the API so each click button has a key
  3. If the button should not be a click button, change its type (e.g. view/miniprogram)
  4. Sanitize menu JSON before calling GetMenuFromJsonResult

Example fix

// before
{ "type": "CLICK", "name": "帮助" } // no key
// after
{ "type": "CLICK", "name": "帮助", "key": "HELP_CLICKED" }
Defensive patterns

Strategy: validation

Validate before calling

foreach (var btn in menuJson.button)
    if (string.Equals(btn.type, "CLICK", StringComparison.OrdinalIgnoreCase) && string.IsNullOrEmpty(btn.key))
        throw new ArgumentException($"Button '{btn.name}' is CLICK but has no key");

Try / catch

try
{
    var menu = CommonApi.GetMenu(appId);
}
catch (WeixinMenuException ex)
{
    logger.LogError(ex, "Menu JSON invalid: {Msg}", ex.Message);
}

Prevention

When it happens

Trigger: Calling GetMenu/GetMenuFromJsonResult on a menu JSON where a button has type "CLICK" but no key field, or a button with a null type.

Common situations: Menus created manually in the Weixin console without setting the click key, older menus saved before key became mandatory, or third-party tools generating malformed menu JSON.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/Senparc.Weixin.MP/Senparc.Weixin.MP/CommonAPIs/Menu/CommonApi.Menu.Common.cs:109

        private static void GetButtonGroup(List<MenuFull_RootButton> rootButtonList, ButtonGroupBase buttonGroup)
        {
            foreach (var rootButton in rootButtonList)
            {
                if (rootButton == null || string.IsNullOrEmpty(rootButton.name))
                {
                    continue; //没有设置一级菜单
                }
                var availableSubButton = rootButton.sub_button == null
                    ? 0
                    : rootButton.sub_button.Count(z => z != null && !string.IsNullOrEmpty(z.name)); //可用二级菜单按钮数量
                if (availableSubButton == 0)
                {
                    //底部单击按钮
                    if (rootButton.type == null ||
                        (rootButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase)
                         && string.IsNullOrEmpty(rootButton.key)))
                    {
                        throw new WeixinMenuException("单击按钮的key不能为空!");
                    }

                    if (rootButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase))
                    {
                        //点击
                        buttonGroup.button.Add(new SingleClickButton()
                        {
                            name = rootButton.name,
                            key = rootButton.key,
                            type = rootButton.type
                        });
                    }
                    else if (rootButton.type.Equals("VIEW", StringComparison.OrdinalIgnoreCase))
                    {
                        //URL
                        buttonGroup.button.Add(new SingleViewButton()
                        {
                            name = rootButton.name,

View on GitHub (pinned to be573f6f94)