{"id":"c6346c7b252b0cef","repo":"spring-projects/spring-framework","slug":"argumentnames-property-of-abstractaspectjadvice","errorCode":null,"errorMessage":"'argumentNames' property of AbstractAspectJAdvice contains an argument name '{}' that is not a valid Java identifier","messagePattern":"'argumentNames' property of AbstractAspectJAdvice contains an argument name '(.+?)' that is not a valid Java identifier","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java","lineNumber":268,"sourceCode":"\t */\n\tpublic void setArgumentNames(String argumentNames) {\n\t\tString[] tokens = StringUtils.commaDelimitedListToStringArray(argumentNames);\n\t\tsetArgumentNamesFromStringArray(tokens);\n\t}\n\n\t/**\n\t * Set by the creator of this advice object if the argument names are known.\n\t * <p>This could be for example because they have been explicitly specified in XML\n\t * or in an advice annotation.\n\t * @param argumentNames list of argument names\n\t */\n\tpublic void setArgumentNamesFromStringArray(@Nullable String... argumentNames) {\n\t\tthis.argumentNames = new String[argumentNames.length];\n\t\tfor (int i = 0; i < argumentNames.length; i++) {\n\t\t\tString argumentName = argumentNames[i];\n\t\t\tthis.argumentNames[i] = argumentName != null ? argumentName.strip() : null;\n\t\t\tif (!isVariableName(this.argumentNames[i])) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"'argumentNames' property of AbstractAspectJAdvice contains an argument name '\" +\n\t\t\t\t\t\tthis.argumentNames[i] + \"' that is not a valid Java identifier\");\n\t\t\t}\n\t\t}\n\t\tif (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {\n\t\t\t// May need to add implicit join point arg name...\n\t\t\tfor (int i = 0; i < this.aspectJAdviceMethod.getParameterCount(); i++) {\n\t\t\t\tClass<?> argType = this.aspectJAdviceMethod.getParameterTypes()[i];\n\t\t\t\tif (argType == JoinPoint.class ||\n\t\t\t\t\t\targType == ProceedingJoinPoint.class ||\n\t\t\t\t\t\targType == JoinPoint.StaticPart.class) {\n\t\t\t\t\t@Nullable String[] oldNames = this.argumentNames;\n\t\t\t\tthis.argumentNames = new String[oldNames.length + 1];\n\t\t\t\tSystem.arraycopy(oldNames, 0, this.argumentNames, 0, i);\n\t\t\t\t\tthis.argumentNames[i] = \"THIS_JOIN_POINT\";\n\t\t\t\t\tSystem.arraycopy(oldNames, i, this.argumentNames, i + 1, oldNames.length - i);\n\t\t\t\t\tbreak;\n\t\t\t\t}","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java#L250-L286","documentation":"Thrown by setArgumentNamesFromStringArray (line 262-272) when one of the supplied argument names fails the isVariableName check (delegated to AspectJProxyUtils.isVariableName). Each argument name must be a syntactically valid Java identifier; this guards later binding of pointcut parameters to advice parameters. It fires during advice setup, typically when parsing an XML 'arg-names' attribute or annotation value.","triggerScenarios":"Calling setArgumentNames(\"foo,123bad,_ok,x y\") or setArgumentNamesFromStringArray(...) with any token that is null, empty, contains spaces/operators, or starts with a digit. Spring's XML <aop:aspect> parser and @AspectJ processing pass the 'argNames' / 'arg-names' attribute straight into this method.","commonSituations":"Typo in the 'arg-names' XML attribute (e.g. trailing comma, stray space, comma between names becoming 'a, ,b'); copying a fully-qualified type name into arg-names instead of the variable name; mixing returning/throwing type names where variable names are expected; encoding/locale issues producing non-identifier characters.","solutions":["Correct the 'arg-names' / 'argNames' value so every token is a legal Java identifier matching a real advice parameter.","Remove trailing commas, empty tokens, and stray whitespace; pass a clean comma-delimited list.","If you intended a type for returning/throwing, put it in the 'returning'/'throwing' attribute instead of arg-names.","Drop the arg-names attribute entirely and let Spring discover names (compile with -parameters) when the mapping is unambiguous."],"exampleFix":"// before\n<aop:after-returning method=\"log\" pointcut=\"args(req)\" returning=\"ret\" arg-names=\"com.example.Result, req\"/>\n// after\n<aop:after-returning method=\"log\" pointcut=\"args(req)\" returning=\"ret\" arg-names=\"ret, req\"/>","handlingStrategy":"validation","validationCode":"// Validate arg-names tokens before calling setArgumentNames(...).\nfor (String token : argNames.split(\",\")) {\n    String t = token.strip();\n    if (t.isEmpty() || !t.chars().limit(1).allMatch(Character::isJavaIdentifierStart())\n            || !t.chars().skip(1).allMatch(Character::isJavaIdentifierPart)) {\n        throw new IllegalArgumentException(\"Invalid arg-names token: \" + token);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    advice.setArgumentNames(argNames);\n} catch (IllegalArgumentException ex) {\n    // surface a clearer config error pointing at the offending element\n    throw new IllegalArgumentException(\"Bad 'arg-names' in aspect config: \" + argNames, ex);\n}","preventionTips":["Treat arg-names as a comma-delimited list of exact Java identifiers only.","Keep arg-names in sync with the advice method signature; update on every signature change.","Prefer compiling with -parameters and omitting arg-names when possible.","Put type narrowing in returning/throwing, never in arg-names."],"tags":["spring-aop","aspectj","argument-binding","configuration","xml"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}