{"record":{"id":"83a7c9cb1f61d65e","repo":"flipped-aurora/gin-vue-admin","slug":"w-83a7c9","errorCode":null,"errorMessage":"设置用户岗位失败: %w","messagePattern":"设置用户岗位失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mcp/org_member_assigner.go","lineNumber":185,"sourceCode":"\t\t} else {\n\t\t\tmessages = append(messages, \"部门均已存在,未写入\")\n\t\t}\n\t\tresult.Departments = &orgAssignChange{Before: currentDeptIDs, After: merged, Added: added}\n\t\t// 上游对 primaryDeptId=0 取部门集合首个;如实回报生效主部门,不因 0 值被 omitempty 隐去而误导\n\t\tresult.PrimaryDeptID = primary\n\t\tif primary == 0 && len(merged) > 0 {\n\t\t\tresult.PrimaryDeptID = merged[0]\n\t\t}\n\t}\n\n\tif len(positionIDs) > 0 {\n\t\tmerged, added := mergeUintSets(currentPositionIDs, positionIDs)\n\t\tif len(added) > 0 {\n\t\t\tif _, err := postUpstream[map[string]any](ctx, \"/user/setUserPositions\", map[string]any{\n\t\t\t\t\"ID\":          user.ID,\n\t\t\t\t\"positionIds\": merged,\n\t\t\t}); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"设置用户岗位失败: %w\", err)\n\t\t\t}\n\t\t\tmessages = append(messages, fmt.Sprintf(\"岗位新增 %v\", added))\n\t\t} else {\n\t\t\tmessages = append(messages, \"岗位均已存在,未写入\")\n\t\t}\n\t\tresult.Positions = &orgAssignChange{Before: currentPositionIDs, After: merged, Added: added}\n\t}\n\n\tresult.AlreadyExists = (result.Departments == nil || len(result.Departments.Added) == 0) &&\n\t\t(result.Positions == nil || len(result.Positions.Added) == 0)\n\tresult.Message = fmt.Sprintf(\"用户 %s(ID:%d) 组织归属分配完成：%s\", user.Username, user.ID, strings.Join(messages, \"；\"))\n\n\treturn textResultWithJSON(\"用户组织归属分配结果：\", result)\n}\n","sourceCodeStart":167,"sourceCodeEnd":200,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/mcp/org_member_assigner.go#L167-L200","documentation":"Wrap of an upstream HTTP error from POST /user/setUserPositions while assigning positions to a member. The tool computed the merged position set but the write to the backend failed; the root cause is preserved with %w.","triggerScenarios":"Handle calls postUpstream to /user/setUserPositions with the merged positionIds and the upstream returns an error (network, auth, invalid position ID, deleted user).","commonSituations":"Position IDs from a stale list (position deleted); MCP token expired; backend API validation rejecting an unknown positionId; transient network blip.","solutions":["Inspect the wrapped cause for the upstream status/body","Validate the positionIds exist via the org query tool before assigning","Verify MCP credentials/permissions for /user/setUserPositions","Retry once the backend service is confirmed healthy"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"for _, pid := range positionIDs {\n    if !knownPositionIDs[pid] {\n        return fmt.Errorf(\"position %d does not exist\", pid)\n    }\n}","typeGuard":null,"tryCatchPattern":"res, err := assigner.Handle(ctx, args)\nif err != nil {\n    if strings.Contains(err.Error(), \"设置用户岗位失败\") {\n        // unwrap and decide: retry on 5xx/network, abort on 4xx validation\n    }\n    return err\n}","preventionTips":["Refresh the position list before assigning; avoid stale cached IDs","Confirm the target user still exists before writing positions","Retry idempotently — the tool merges sets, so re-running is safe"],"tags":["network","upstream-api","mcp","positions"],"backgroundTag":"upstream-api-call-failed","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}