flipped-aurora/gin-vue-admin · error

单次授权菜单数量不能超过 %d 个

Error message

单次授权菜单数量不能超过 %d 个

What it means

The role-menu assigner caps a single authorization call at `orgBatchLimit` menu IDs to avoid oversized payloads and long-running casbin writes. Exceeding the cap aborts before any upstream call. The message interpolates the configured maximum.

Source

Thrown at server/mcp/role_menu_assigner.go:70

	)
}

func (r *RoleMenuAssigner) Handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	args := request.GetArguments()

	authorityID, err := parseAuthorityID(args["authorityId"])
	if err != nil {
		return nil, err
	}
	menuIDs, err := parseUintList(args["menuIds"], "menuIds")
	if err != nil {
		return nil, err
	}
	if err := requireNonEmptyList(menuIDs, "menuIds"); err != nil {
		return nil, err
	}
	if len(menuIDs) > orgBatchLimit {
		return nil, fmt.Errorf("单次授权菜单数量不能超过 %d 个", orgBatchLimit)
	}

	// 全量基础菜单:存在性校验、父链补齐、写回时的完整菜单对象都从这里取
	allResp, err := postUpstream[[]system.SysBaseMenu](ctx, "/menu/getMenuList", map[string]any{})
	if err != nil {
		return nil, fmt.Errorf("获取菜单列表失败: %w", err)
	}
	menuIndex := make(map[uint]system.SysBaseMenu)
	flattenBaseMenus(allResp.Data, menuIndex)

	for _, id := range menuIDs {
		if _, ok := menuIndex[id]; !ok {
			return nil, fmt.Errorf("菜单 %d 不存在,可先用 list_all_menus 查询全部菜单", id)
		}
	}

	// 角色当前授权(先读,防覆盖丢权)
	currentResp, err := postUpstream[map[string][]system.SysMenu](ctx, "/menu/getMenuAuthority", map[string]any{

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Split menuIds into batches no larger than orgBatchLimit and call the tool once per batch
  2. Pre-filter menuIds to only the menus actually needed (sub-menus often come along with parents automatically — the tool补齐父链)
  3. If bulk setup is required, script multiple sequential calls and verify with a role-menu query tool

Example fix

// before
assignMenus(authorityID, allMenuIDs) // 200 ids > limit
// after
for batch := range chunk(allMenuIDs, orgBatchLimit) {
    assignMenus(authorityID, batch)
}
Defensive patterns

Strategy: validation

Validate before calling

if len(menuIDs) > orgBatchLimit {
    return fmt.Errorf("chunk menuIds: %d exceeds limit %d", len(menuIDs), orgBatchLimit)
}
for batch := range chunk(menuIDs, orgBatchLimit) {
    if err := assignMenus(ctx, authorityID, batch); err != nil {
        return err
    }
}

Prevention

When it happens

Trigger: Calling the assign-menus tool with a menuIds array longer than orgBatchLimit (e.g. attempting to grant every menu of the system in one call).

Common situations: Bulk-provisioning a new super-admin role from a script; migrating permissions between environments in one shot; generating menuIds from a wide query without chunking.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/d18239274b9d417b. Report an issue: GitHub.