{"record":{"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/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/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, 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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the offending token printed in the message and correct it to a valid Java identifier (letters, digits, underscore, $; not starting with a digit).","Remove trailing/leading whitespace and stray commas from the arg-names string; StringUtils.commaDelimitedListToStringArray does not strip delimiters.","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).","If you intended a type rather than a variable, use the returning/throwing attribute instead of arg-names."],"exampleFix":"// before\n<aop:after-returning method=\"after\"\n    pointcut=\"execution(* *(..)) && args(payload)\"\n    arg-names=\"payload,returning-val\" returning=\"returning-val\"/>\n\n// after — use valid Java identifiers only, no hyphens\n<aop:after-returning method=\"after\"\n    pointcut=\"execution(* *(..)) && args(payload)\"\n    arg-names=\"payload,returningVal\" returning=\"returningVal\"/>","handlingStrategy":"validation","validationCode":"// Validate arg-names tokens before passing to setArgumentNames.\nimport java.util.regex.Pattern;\nprivate static final Pattern JAVA_IDENT = Pattern.compile(\"^[A-Za-z_$][A-Za-z0-9_$]*$\");\n\nvoid safeSetArgumentNames(AbstractAspectJAdvice advice, String argNames) {\n    for (String token : argNames.split(\",\")) {\n        String t = token.strip();\n        if (!JAVA_IDENT.matcher(t).matches()) {\n            throw new IllegalArgumentException(\"Invalid arg-name token: '\" + t + \"'\");\n        }\n    }\n    advice.setArgumentNames(argNames);\n}","typeGuard":"boolean isValidArgName(String token) {\n    if (token == null || token.isBlank()) return false;\n    if (!Character.isJavaIdentifierStart(token.charAt(0))) return false;\n    for (int i = 1; i < token.length(); i++) {\n        if (!Character.isJavaIdentifierPart(token.charAt(i))) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    advice.setArgumentNames(argNames);\n} catch (IllegalArgumentException ex) {\n    // log the offending token and surface a config-level error to the user\n}","preventionTips":["Treat arg-names as bare Java identifiers; never put types or hyphenated names there.","Strip and validate each token before calling setArgumentNames.","Let Spring auto-insert the joinpoint slot — do not include it in arg-names."],"tags":["spring-aop","aspectj","argument-binding","configuration","validation"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}