flipped-aurora/gin-vue-admin · error

菜单授权写回失败: %w

Error message

菜单授权写回失败: %w

What it means

Thrown when the write-back step of the role-menu assigner fails: POST /menu/addMenuAuthority with the merged (existing + new + auto-added parents) menu payload returned an error. The read succeeded and a merged payload was built, but persisting the new authorization set to the upstream server failed.

Source

Thrown at server/mcp/role_menu_assigner.go:170

		return textResultWithJSON("角色菜单授权结果:", result)
	}

	// 全量写回:当前授权中已被删除的基础菜单构造最小对象原样保留,不因本次授权而丢失
	payload := make([]system.SysBaseMenu, 0, len(merged))
	for _, id := range merged {
		if menu, ok := menuIndex[id]; ok {
			payload = append(payload, menu)
			continue
		}
		var placeholder system.SysBaseMenu
		placeholder.ID = id
		payload = append(payload, placeholder)
	}
	if _, err := postUpstream[map[string]any](ctx, "/menu/addMenuAuthority", map[string]any{
		"authorityId": authorityID,
		"menus":       payload,
	}); err != nil {
		return nil, fmt.Errorf("菜单授权写回失败: %w", err)
	}

	result.Message = fmt.Sprintf("成功为角色 %d 新增 %d 个菜单授权(含自动补齐父级 %d 个),当前共 %d 个",
		authorityID, len(added), len(result.ParentAutoAdded), len(merged))
	return textResultWithJSON("角色菜单授权结果:", result)
}

// flattenBaseMenus 把基础菜单树摊平成 id→菜单 映射
func flattenBaseMenus(list []system.SysBaseMenu, into map[uint]system.SysBaseMenu) {
	for i := range list {
		into[list[i].ID] = list[i]
		if len(list[i].Children) > 0 {
			flattenBaseMenus(list[i].Children, into)
		}
	}
}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Re-run the assignment after confirming the upstream server is healthy — the tool is idempotent since it re-reads current grants.
  2. Check the MCP client's JWT is still valid and has access to /menu/addMenuAuthority in Casbin.
  3. Verify the authorityId still exists before invoking the tool.
  4. Inspect the wrapped cause for HTTP status; a 403 points to permissions, 500 to upstream bugs.
  5. For large payloads, check reverse-proxy body size/timeouts.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the role still exists and the token grants menu APIs before write-back
if !roleExists(authorityID) { return fmt.Errorf("authority %d missing", authorityID) }
if !canAccess("/menu/addMenuAuthority") { return fmt.Errorf("token lacks menu write permission") }

Try / catch

_, err := postUpstream[map[string]any](ctx, "/menu/addMenuAuthority", body)
if err != nil {
    log.Printf("addMenuAuthority failed for role %d: %v", authorityID, err)
    // safe to retry: the tool re-reads current grants on next run
    return err
}

Prevention

When it happens

Trigger: Handle() reaches the addMenuAuthority call with authorityId and menus payload, and postUpstream fails: upstream down, 401/403 (Casbin denies the endpoint), invalid authorityId (role deleted between read and write), malformed payload causing upstream validation error, or network timeout.

Common situations: Backend restarted mid-operation; token expired between the two calls; role deleted concurrently by another admin; proxy timeout on large menu payloads; permission for the menu-management API revoked from the MCP user.

Related errors


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