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

  1. Use only the supported abbreviations: 'r' for read, 'w' or 'rw' for write.
  2. Map human-readable action names to abbreviations at the API/controller layer before passing to the service.
  3. 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

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.