flipped-aurora/gin-vue-admin · error

菜单 %d 不存在,可先用 list_all_menus 查询全部菜单

Error message

菜单 %d 不存在,可先用 list_all_menus 查询全部菜单

What it means

Each requested menu ID must exist in the flattened index of the server's menu list. An unknown ID is rejected with a hint to use the list_all_menus tool to discover valid IDs. This prevents writing menu-authority rows for menus that do not exist.

Source

Thrown at server/mcp/role_menu_assigner.go:83

	}
	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{
		"authorityId": authorityID,
	})
	if err != nil {
		return nil, fmt.Errorf("获取角色当前菜单授权失败: %w", err)
	}
	currentIDs := make([]uint, 0)
	for _, menu := range currentResp.Data["menus"] {
		id := menu.MenuId
		if id == 0 {
			id = menu.ID
		}
		if id != 0 && !containsUint(currentIDs, id) {
			currentIDs = append(currentIDs, id)

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Call the list_all_menus MCP tool to get the current valid menu IDs and correct the list
  2. Remove or replace the stale ID in menuIds
  3. Install/enable the missing plugin if the menu belongs to a plugin
  4. Re-seed or restore the menu if it was accidentally deleted server-side

Example fix

// before
menuIds := []uint{1, 2, 333} // 333 doesn't exist
// after
// verify via list_all_menus first
menuIds := []uint{1, 2, 18}
Defensive patterns

Strategy: validation

Validate before calling

// fetch valid menu IDs via list_all_menus first
all, err := listAllMenus(ctx)
if err != nil {
    return err
}
valid := make(map[uint]struct{}, len(all))
for _, m := range all {
    valid[m.ID] = struct{}{}
}
for _, id := range menuIDs {
    if _, ok := valid[id]; !ok {
        return fmt.Errorf("menu %d not found", id)
    }
}

Type guard

func allMenusExist(ids []uint, index map[uint]struct{}) bool {
    for _, id := range ids {
        if _, ok := index[id]; !ok {
            return false
        }
    }
    return true
}

Prevention

When it happens

Trigger: Calling the assign-menus tool with a menuIds entry absent from the server's menu tree: typo, ID from another environment, soft-deleted menu, or an ID belonging to a plugin not installed.

Common situations: Hardcoded menu IDs drifting across environments after re-seeding menus; menu removed in a newer gva version; plugin menus missing because the plugin wasn't installed.

Related errors


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