导读:本期聚焦于天马创作的《微信公众号菜单配置报错40016怎么解决?不合法的按钮个数限制说明》,敬请观看详情。为什么提交自定义菜单 JSON 后总是返回 40016?这个错误码在微信公众平台文档中对应不合法的按钮个数,但真正原因往往不是按钮总数过多,而是一级菜单超过 3 个或某个一级菜单下的二级菜单超过 5 个。文章围绕微信自定义菜单的层级限制展开,说明 button 数组和 sub_button 数组的合法范围,结合常见的空数组、子菜单数量越界、一级菜单超限等场景,演示如何打印请求体并借助校验脚本快速定位问题。同时提供修复后的菜单结构示例和避免再次触发 40016 的思路。读完可以按照平台规则调整菜单 JSON,使配置一次通过创建接口。

在微信公众平台配置自定义菜单时,接口返回错误码 40016 表示提交的按钮数量不符合平台规定。这个错误通常与菜单结构中的 button 数组或 sub_button 数组长度有关。很多菜单请求在客户端看起来正常,但发送到微信服务器后被拦截,正是因为平台对一级菜单和二级菜单分别做数量校验,而不是只看按钮总数。

要准确理解 40016,需要先明确微信自定义菜单的层级设计。自定义菜单由一级菜单数组 button 组成,每个一级菜单可以包含二级菜单数组 sub_button。微信服务器校验请求体时,会分别检查这两个数组的长度,任何一层不满足要求都会返回 errcode 为 40016,错误信息通常写作 invalid button size,中文提示为不合法的按钮个数。

一、40016错误码的准确含义

微信公众平台接口返回的 errcode 为 40016 时,表示菜单按钮数量不合法。菜单创建接口的返回体通常包含 errcodeerrmsg 两个字段。当 errmsg 显示为 invalid button size 或中文提示不合法的按钮个数时,就应该把排查范围锁定在 button 数组和 sub_button 数组的长度上。

这个错误码与权限、参数格式、网络波动等无关,它只关注按钮数量。之所以会出现 40016,是因为微信自定义菜单的数据结构不是一个简单的扁平按钮列表,而是分成两个层级。一级菜单数组 button 最多允许 3 个元素,每个一级菜单下的二级菜单数组 sub_button 最多允许 5 个元素。平台校验时会对这两个层级分别计数,任何一层超出限制都会直接拒绝创建请求。

还有一个容易被忽略的细节:如果某个一级菜单包含 sub_button 字段,那么即使这个一级菜单本身配置了 name,它也不会作为可点击按钮触发事件,它只承担容器角色。此时按钮计数的核心不是简单的总数相加减,而是分层限制。换句话说,即便你认为实际显示的按钮总数没有超过某个数值,只要某一层级的数组长度越界,依然会返回 40016。

二、按钮个数限制的具体规则

微信官方对自定义菜单的层级数量限制非常明确。button 数组长度必须为 1 到 3。也就是说,创建一个完全不包含 button 字段的菜单,或者 button 数组长度大于 3,都会触发 40016。同样地,sub_button 数组长度必须为 1 到 5。如果某个一级菜单配置了二级菜单,但 sub_button 是空数组或者包含超过 5 个对象,也会不符合要求。

以一个合规结构为例,最外层 button 包含 3 个一级菜单:第一个一级菜单没有子菜单,第二个一级菜单包含 3 个二级菜单,第三个一级菜单包含 5 个二级菜单。此时一级菜单个数为 3,二级菜单个数分别为 0、3、5,均未越界。后端接收的按钮节点总数为 11 个,但微信不会只按照总节点数来检查,而是会同时检查每一个 button 元素内部的 sub_button 数组长度。

如果第三个一级菜单下放置了 6 个二级菜单,即便 button 数组长度仍然为 3,接口依然会返回 40016。这就是很多配置看似一级菜单数量没有超过 3 个却报错的原因。因此排查时不能只盯着顶层菜单数量,还需要逐个检查二级菜单数组。

三、常见触发40016的场景与示例

第一种常见场景是一级菜单数组写成了 4 个。比如系统早期默认生成三个一级菜单,后来运营人员又新增了一个跳转入口,结果 button 数组长度变成 4。微信平台不允许超过 3 个一级菜单,提交后就会返回 40016。这类问题通常需要回到菜单配置逻辑中,去掉多余的一级菜单,或者把入口合并到已有菜单下。

第二种常见场景是二级菜单超过 5 个。开发者把一组功能全部挂在同一个一级菜单下,sub_button 添加了 6 个甚至更多。微信规定每个一级菜单最多只能包含 5 个二级菜单,超过后直接报错。下面这个 JSON 示例中,一级菜单数量为 2,但第二个一级菜单下配置了 6 个二级菜单,因此会触发 40016。

{
  "button": [
    {
      "name": "一级菜单A",
      "sub_button": []
    },
    {
      "name": "一级菜单B",
      "sub_button": [
        {"type": "click", "name": "子菜单1", "key": "K1"},
        {"type": "click", "name": "子菜单2", "key": "K2"},
        {"type": "click", "name": "子菜单3", "key": "K3"},
        {"type": "click", "name": "子菜单4", "key": "K4"},
        {"type": "click", "name": "子菜单5", "key": "K5"},
        {"type": "click", "name": "子菜单6", "key": "K6"}
      ]
    }
  ]
}

第三种常见场景是 sub_button 为空数组。有些配置生成逻辑会先创建父级菜单,子菜单为空数组,后续再异步填充。但微信接口在创建菜单时会把空数组判定为不合法按钮个数。因此只要某个一级菜单包含 sub_button 字段,就必须保证该数组至少包含 1 个二级菜单对象。

此外,还有一种情况是菜单 JSON 在序列化或传输过程中产生了重复对象或空对象,导致字段丢失。这类问题虽然不一定直接由按钮个数引起,但同样可能让微信返回 40016。排查时最好打印实际提交的 JSON 内容,而不是依赖前端页面展示出来的按钮样式。

四、如何快速定位并修复40016

遇到 40016 后,第一步是打印请求体。可以把准备提交的菜单 JSON 序列化后写入日志,查看 button 数组长度和每个对象的 sub_button 长度。不要只依赖调试界面,因为界面展示的是渲染后的按钮,与实际提交的 JSON 结构可能存在差异。如果团队后端的菜单模型比较复杂,还可以在拼接菜单的代码中加入长度检测。

第二步是用脚本校验。下面是一段 Python 脚本,读取菜单 JSON 并输出各层级按钮数量。只要打印结果中显示一级菜单数量大于 3,或者某个一级菜单下的二级菜单数量大于 5,就能立即定位错误位置。

import json

def check_menu(menu_json: str):
    data = json.loads(menu_json)
    buttons = data.get("button", [])
    print(f"一级菜单数量: {len(buttons)}")
    if len(buttons) > 3:
        print("错误: 一级菜单超过3个")
    for index, btn in enumerate(buttons):
        sub_buttons = btn.get("sub_button", [])
        print(f"第{index + 1}个一级菜单的子菜单数量: {len(sub_buttons)}")
        if len(sub_buttons) > 5:
            print("错误: 该一级菜单下的二级菜单超过5个")
        if "sub_button" in btn and len(sub_buttons) == 0:
            print("错误: 二级菜单数组不能为空")

第三步是修正菜单结构。如果一级菜单超过 3 个,需要删减或合并;如果某个一级菜单下的二级菜单超过 5 个,可以把部分子菜单拆分到其他一级菜单下。若确实需要更多子菜单,可以考虑使用小程序、网页链接或客服消息来扩展功能,而不是尝试突破微信给自定义菜单设定的按钮个数限制。

修复后重新调用菜单创建接口。如果仍然返回 40016,再检查是否存在不可见字符、按钮对象是否为空、name 字段是否为空白等连带问题。只有确保 button 数组长度在 1 到 3 之间,且每个 sub_button 数组长度在 1 到 5 之间,才能通过按钮个数校验,让菜单配置一次提交成功。

微信公众号自定义菜单40016按钮个数限制修改时间:2026-08-25 12:18:29

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。