Tencent/APIJSON · error · IllegalArgumentException

角色 {} 不存在!只能是[{}]中的一种!

Error message

角色 {} 不存在!只能是[{}]中的一种!

What it means

Inside verifyAccess(), after the table is resolved, the role string taken from config.getRole() must exist in the static ROLE_MAP. ROLE_MAP holds the well-known APIJSON roles (ADMIN, OWNER, CONTACT, MEMBER, CIRCLE, UNKNOWN and friends); an unrecognized name throws IllegalArgumentException together with the list of legal names. This is a request-contract error: the client sent a role APIJSON cannot map.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java:277

	public boolean verifyAccess(SQLConfig<T, M, L> config) throws Exception {
		if (ENABLE_VERIFY_ROLE == false) {
			throw new UnsupportedOperationException("AbstractVerifier.ENABLE_VERIFY_ROLE == false " +
                    "时不支持校验角色权限!如需支持则设置 AbstractVerifier.ENABLE_VERIFY_ROLE = true !");
		}

		String table = config == null ? null : config.getTable();
		if (table == null) {
			return true;
		}

		String role = config.getRole();
		if (role == null) {
			role = UNKNOWN;
		}
		else {
			if (ROLE_MAP.containsKey(role) == false) {
				Set<String> NAMES = ROLE_MAP.keySet();
				throw new IllegalArgumentException("角色 " + role + " 不存在!" +
                        "只能是[" + StringUtil.get(NAMES.toArray()) + "]中的一种!");
			}

			if (role.equals(UNKNOWN) == false) { //未登录的角色
				verifyLogin();
			}
		}

		RequestMethod method = config.getMethod();
		verifyRole(config, table, method, role);

		return true;
	}

	@Override
	public void verifyRole(SQLConfig<T, M, L> config, String table, RequestMethod method, String role) throws Exception {
		verifyAllowRole(config, table, method, role); //验证允许的角色
		verifyUseRole(config, table, method, role); //验证使用的角色

View on GitHub (pinned to 5284052872)

Solutions

  1. Change the request to use one of the roles printed in the message (they come from ROLE_MAP.keySet(), e.g. ADMIN, OWNER, CONTACT, CIRCLE, MEMBER, UNKNOWN).
  2. Check for case/spelling typos in the "role" value in the request JSON — matching is exact and case-sensitive.
  3. If a custom role is genuinely needed, extend the verifier and populate ROLE_MAP (or override verifyAccess/verifyRole) in your subclass instead of sending an unregistered name.
  4. Omit the role key entirely to fall back to UNKNOWN/anonymous handling when that is the intent.

Example fix

// before
{
  "User": { "id": 1 },
  "role": "superuser",
  "tag": "User"
}

// after
{
  "User": { "id": 1 },
  "role": "OWNER",
  "tag": "User"
}
Defensive patterns

Strategy: validation

Validate before calling

Set<String> allowed = AbstractVerifier.ROLE_MAP.keySet();
if (role != null && !allowed.contains(role)) {
    throw new ClientError("role must be one of " + allowed + ", got " + role);
}

Type guard

boolean isValidRole(String r) { return r == null || AbstractVerifier.ROLE_MAP.containsKey(r); }

Try / catch

catch (IllegalArgumentException e) when message starts with "角色" -> map to HTTP 400 with the allowed-role list from ROLE_MAP.keySet().

Prevention

When it happens

Trigger: A request object carries "role":"SUPERUSER" (or a typo like "ownner", or a localized/empty-string role) and the request reaches verifyAccess; ROLE_MAP.containsKey(role) is false and the exception lists the allowed role names.

Common situations: Client and server disagree on the role vocabulary; front-end sends an application-specific role that was never registered; case mismatch ("owner" vs "OWNER"); migrating from an older APIJSON whose role list differed.

Related errors


AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14). Data as JSON: /api/errors/9983eb6d6e2f404c. Report an issue: GitHub.