alibaba/nacos · warning · IllegalArgumentException
unsupported action: {action}
Error message
unsupported action: {action} What it means
Thrown by VisibilityGrantRoleHelper.normalizeStoredAction() when the action parameter, after trimming and lowercasing, is not one of 'r', 'w', or 'rw'. This is the raw IllegalArgumentException; within the normal service flow it is caught by DefaultVisibilityGrantService.normalizeGrantAction() and re-wrapped as NacosApiException (error 1355). The helper accepts only these three action codes and rejects anything else.
Source
Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/visibility/VisibilityGrantRoleHelper.java:64
}
static String normalizeResourceType(String resourceType) {
return StringUtils.isBlank(resourceType) ? resourceType
: resourceType.trim().toLowerCase(Locale.ROOT);
}
static String normalizeStoredAction(String action) {
if (StringUtils.isBlank(action)) {
throw new IllegalArgumentException("action is blank");
}
String normalized = action.trim().toLowerCase(Locale.ROOT);
if ("r".equals(normalized)) {
return "r";
}
if ("w".equals(normalized) || "rw".equals(normalized)) {
return "rw";
}
throw new IllegalArgumentException("unsupported action: " + action);
}
static boolean matchesRequestedAction(String storedAction, String requestedAction) {
String normalizedRequested = normalizeStoredAction(requestedAction);
if ("rw".equals(normalizedRequested)) {
return "rw".equals(storedAction);
}
return "r".equals(storedAction) || "rw".equals(storedAction);
}
static String buildUserRoleName(String username) {
if (StringUtils.isBlank(username)) {
throw new IllegalArgumentException("username is blank");
}
// Use a deterministic short SHA-256 prefix so internal role names stay within
// the existing roles.role varchar(50) limit and do not expose user names.
return buildUserRoleNamePrefix() + sha256LowerHex(username).substring(0,
USER_ROLE_HASH_HEX_LENGTH);View on GitHub (pinned to 9b989acdf1)
Solutions
- Use only the supported abbreviations: 'r' for read, 'w' or 'rw' for write.
- Map human-readable action names to abbreviations at the API/controller layer before passing to the service.
- Add a whitelist check before calling normalizeStoredAction.
Example fix
// before: may throw for unrecognized actions
String stored = VisibilityGrantRoleHelper.normalizeStoredAction(action);
// after: whitelist valid actions
private static final Set<String> VALID_ACTIONS = Set.of("r", "w", "rw");
String normalized = action == null ? "" : action.trim().toLowerCase(Locale.ROOT);
if (!VALID_ACTIONS.contains(normalized)) {
throw new IllegalArgumentException(
"Unsupported action: " + action + ". Use 'r', 'w', or 'rw'.");
}
String stored = VisibilityGrantRoleHelper.normalizeStoredAction(action); Defensive patterns
Strategy: validation
Validate before calling
// Whitelist valid actions before calling normalizeStoredAction
private static final Set<String> VALID_ACTIONS = Set.of("r", "w", "rw");
String normalized = action == null ? "" : action.trim().toLowerCase(Locale.ROOT);
if (!VALID_ACTIONS.contains(normalized)) {
throw new IllegalArgumentException(
"Unsupported action '" + action + "'. Valid: r, w, rw");
}
String stored = VisibilityGrantRoleHelper.normalizeStoredAction(action); Type guard
public static boolean isSupportedAction(String action) {
if (action == null) return false;
String normalized = action.trim().toLowerCase(Locale.ROOT);
return Set.of("r", "w", "rw").contains(normalized);
} Try / catch
try {
String stored = VisibilityGrantRoleHelper.normalizeStoredAction(action);
} catch (IllegalArgumentException e) {
// "unsupported action: xxx" — map to a user-friendly error
log.warn("Unsupported action '{}': {}", action, e.getMessage());
throw e;
} Prevention
- Use a whitelist of valid action values ('r', 'w', 'rw') at the input layer.
- Map human-readable action names to abbreviations before calling the helper.
- Document the supported action codes in API documentation.
When it happens
Trigger: Calling normalizeStoredAction with an action like 'read', 'write', 'delete', 'admin', 'x', or any string that isn't 'r', 'w', or 'rw' (case-insensitive). Also thrown internally by matchesRequestedAction() which calls normalizeStoredAction on the requested action.
Common situations: A client sends a full word ('read', 'write') instead of the abbreviation; a typo in the action field; an unexpected action value from a misconfigured client or integration.
Related errors
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/5b53f445fed2bf44.
Report an issue: GitHub.