flipped-aurora/gin-vue-admin · error

未找到 ID 为 %d 的用户(已扫描前 %d 条,大用户量场景请传 username 参数精确定位)

Error message

未找到 ID 为 %d 的用户(已扫描前 %d 条,大用户量场景请传 username 参数精确定位)

What it means

findUserByID exhausts its scan: upstream getUserList lacks ID filtering, so the tool scans up to 20 pages of 100 users (2000 records). If the target ID never appears (or the user is outside the caller's data-scope visibility), this error is returned with guidance to pass a username hint.

Source

Thrown at server/mcp/org_common.go:256

			return nil, fmt.Errorf("获取用户列表失败: %w", err)
		}
		for i := range resp.Data.List {
			if resp.Data.List[i].ID == userID {
				return &resp.Data.List[i], nil
			}
		}
		// hint 仅是加速命中的优化;username 为 LIKE 模糊匹配且只查首页,未命中(名不匹配或
		// 命中过多致目标不在首页)时不误报,回退全量翻页扫描兜底
	}

	found, _, err := scanUsersByIDs(ctx, []uint{userID})
	if err != nil {
		return nil, err
	}
	if user, ok := found[userID]; ok {
		return &user, nil
	}
	return nil, fmt.Errorf("未找到 ID 为 %d 的用户(已扫描前 %d 条,大用户量场景请传 username 参数精确定位)", userID, orgUserScanMaxPages*orgUserScanPageSize)
}

// requireNonEmptyList 语义化的必填列表校验
func requireNonEmptyList(ids []uint, name string) error {
	if len(ids) == 0 {
		return errors.New(name + " 参数是必需的,且至少包含一个ID")
	}
	return nil
}

// parseOptionalPositiveInt 解析可选的正整数分页参数,兼容数字与字符串两种形式
// (与本工具集"数字参数兼容字符串"的既定设计一致);缺省或非法时返回 def
func parseOptionalPositiveInt(v any, def int) int {
	switch value := v.(type) {
	case float64:
		if value >= 1 {
			return int(value)
		}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Pass the username parameter so the tool can locate the user precisely via the LIKE filter
  2. Verify the userId is correct and the user exists in the admin UI
  3. Check the user is within the MCP token's data-scope visible range
  4. Confirm the user has not been deleted
  5. If the deployment is very large and username unknown, look up the ID in the frontend first

Example fix

// before
{"userId": 8873}
// after
{"userId": 8873, "username": "zhangsan"}  // precise locate, avoids 2000-row scan
Defensive patterns

Strategy: validation

Validate before calling

// resolve the user first via a direct lookup, only call the assign tool with a confirmed ID + username
const user = await findUserByUsername(username)
if (!user) throw new Error('target user does not exist')
// then pass both: { userId: user.ID, username: user.username }

Try / catch

try {
  await callMcpTool('assign_user_org', args)
} catch (e) {
  if (/未找到 ID 为 \d+ 的用户/.test(e.message)) {
    // re-call with username hint, or verify the ID/data-scope visibility in the admin UI
  }
}

Prevention

When it happens

Trigger: Requesting an org operation on a userId whose record is not within the first 2000 visible rows of /user/getUserList, the user does not exist, or the row is hidden by the caller's data-scope permissions.

Common situations: Large deployments with >2000 users where the target user sits beyond the scan limit; userId typo or from another environment; data-scope engine filters the row out for this token; user soft-deleted.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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