spring-projects/spring-framework · error · IllegalArgumentException

'argumentNames' property of AbstractAspectJAdvice contains…

Error message

'argumentNames' property of AbstractAspectJAdvice contains an argument name '{}' that is not a valid Java identifier

What it means

Thrown by setArgumentNamesFromStringArray (line 262-272) when one of the supplied argument names fails the isVariableName check (delegated to AspectJProxyUtils.isVariableName, which requires a valid Java identifier). The argument names are later used to bind pointcut parameters to advice parameters, so Spring validates them eagerly rather than failing later during matching.

Solutions

  1. Inspect the offending token printed in the message and correct it to a valid Java identifier (letters, digits, underscore, $; not starting with a digit).
  2. Remove trailing/leading whitespace and stray commas from the arg-names string; StringUtils.commaDelimitedListToStringArray does not strip delimiters.
  3. Do not include the implicit thisJoinPoint / thisJoinPointStaticPart parameter in arg-names — Spring inserts 'THIS_JOIN_POINT' automatically when the parameter count is one greater (see lines 273-288).
  4. If you intended a type rather than a variable, use the returning/throwing attribute instead of arg-names.

Example fix

// before
<aop:after-returning method="after"
    pointcut="execution(* *(..)) && args(payload)"
    arg-names="payload,returning-val" returning="returning-val"/>

// after — use valid Java identifiers only, no hyphens
<aop:after-returning method="after"
    pointcut="execution(* *(..)) && args(payload)"
    arg-names="payload,returningVal" returning="returningVal"/>
Defensive patterns

Strategy: validation

Validate before calling

// Validate arg-names tokens before passing to setArgumentNames.
import java.util.regex.Pattern;
private static final Pattern JAVA_IDENT = Pattern.compile("^[A-Za-z_$][A-Za-z0-9_$]*$");

void safeSetArgumentNames(AbstractAspectJAdvice advice, String argNames) {
    for (String token : argNames.split(",")) {
        String t = token.strip();
        if (!JAVA_IDENT.matcher(t).matches()) {
            throw new IllegalArgumentException("Invalid arg-name token: '" + t + "'");
        }
    }
    advice.setArgumentNames(argNames);
}

Type guard

boolean isValidArgName(String token) {
    if (token == null || token.isBlank()) return false;
    if (!Character.isJavaIdentifierStart(token.charAt(0))) return false;
    for (int i = 1; i < token.length(); i++) {
        if (!Character.isJavaIdentifierPart(token.charAt(i))) return false;
    }
    return true;
}

Try / catch

try {
    advice.setArgumentNames(argNames);
} catch (IllegalArgumentException ex) {
    // log the offending token and surface a config-level error to the user
}

Prevention

When it happens

Trigger: Calling setArgumentNames("retVal, 1stArg") or passing a name with a space, dot, hyphen, leading digit, or empty string. Typically happens with XML <aop:aspect> 'arg-names' attributes containing typos, or programmatic registration of advice where arg-names is built by string concatenation.

Common situations: Typos in the XML arg-names attribute, copy-pasting a fully-qualified type name into arg-names (it expects bare variable names), trailing commas producing an empty token, or whitespace-only tokens after splitting. Also seen when someone puts the JoinPoint parameter name in the list manually with a non-identifier placeholder.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/c6346c7b252b0cef. Report an issue: GitHub.

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:268

	 */
	public void setArgumentNames(String argumentNames) {
		String[] tokens = StringUtils.commaDelimitedListToStringArray(argumentNames);
		setArgumentNamesFromStringArray(tokens);
	}

	/**
	 * Set by the creator of this advice object if the argument names are known.
	 * <p>This could be for example because they have been explicitly specified in XML
	 * or in an advice annotation.
	 * @param argumentNames list of argument names
	 */
	public void setArgumentNamesFromStringArray(@Nullable String... argumentNames) {
		this.argumentNames = new String[argumentNames.length];
		for (int i = 0; i < argumentNames.length; i++) {
			String argumentName = argumentNames[i];
			this.argumentNames[i] = argumentName != null ? argumentName.strip() : null;
			if (!isVariableName(this.argumentNames[i])) {
				throw new IllegalArgumentException(
						"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
						this.argumentNames[i] + "' that is not a valid Java identifier");
			}
		}
		if (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {
			// May need to add implicit join point arg name...
			for (int i = 0; i < this.aspectJAdviceMethod.getParameterCount(); i++) {
				Class<?> argType = this.aspectJAdviceMethod.getParameterTypes()[i];
				if (argType == JoinPoint.class ||
						argType == ProceedingJoinPoint.class ||
						argType == JoinPoint.StaticPart.class) {
					@Nullable String[] oldNames = this.argumentNames;
				this.argumentNames = new String[oldNames.length + 1];
				System.arraycopy(oldNames, 0, this.argumentNames, 0, i);
					this.argumentNames[i] = "THIS_JOIN_POINT";
					System.arraycopy(oldNames, i, this.argumentNames, i + 1, oldNames.length - i);
					break;
				}

View on GitHub (pinned to 69bf83ad71)