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
- Re-run the assignment after confirming the upstream server is healthy — the tool is idempotent since it re-reads current grants.
- Check the MCP client's JWT is still valid and has access to /menu/addMenuAuthority in Casbin.
- Verify the authorityId still exists before invoking the tool.
- Inspect the wrapped cause for HTTP status; a 403 points to permissions, 500 to upstream bugs.
- 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
- Re-run the tool after fixing transient issues — it is idempotent due to the pre-read.
- Avoid deleting roles while assignments are in flight.
- Keep token lifetime longer than the operation window or use auto-refresh.
- Monitor upstream 5xx rates on menu endpoints.
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.