{"record":{"id":"a63147d9a998af8a","repo":"spring-projects/spring-framework","slug":"placeholder-match-is-not-valid","errorCode":null,"errorMessage":"Placeholder [{match}] is not valid","messagePattern":"Placeholder \\[(.+?)\\] is not valid","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java","lineNumber":397,"sourceCode":"\t\tString[] argumentTypeShortNames = new String[argumentTypes.length];\n\t\tfor (int i = 0; i < argumentTypeShortNames.length; i++) {\n\t\t\targumentTypeShortNames[i] = ClassUtils.getShortName(argumentTypes[i]);\n\t\t}\n\t\tmatcher.appendReplacement(output,\n\t\t\t\tMatcher.quoteReplacement(StringUtils.arrayToCommaDelimitedString(argumentTypeShortNames)));\n\t}\n\n\t/**\n\t * Checks to see if the supplied {@code String} has any placeholders\n\t * that are not specified as constants on this class and throws an\n\t * {@code IllegalArgumentException} if so.\n\t */\n\tprivate static void checkForInvalidPlaceholders(String message) throws IllegalArgumentException {\n\t\tMatcher matcher = PATTERN.matcher(message);\n\t\twhile (matcher.find()) {\n\t\t\tString match = matcher.group();\n\t\t\tif (!ALLOWED_PLACEHOLDERS.contains(match)) {\n\t\t\t\tthrow new IllegalArgumentException(\"Placeholder [\" + match + \"] is not valid\");\n\t\t\t}\n\t\t}\n\t}\n\n}\n","sourceCodeStart":379,"sourceCodeEnd":403,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java#L379-L403","documentation":"Thrown by checkForInvalidPlaceholders (line 392-399) when a trace message template (enterMessage/exitMessage/exceptionMessage) set on CustomizableTraceInterceptor contains a placeholder token matching the regex $[Alpha]+ that is not in the ALLOWED_PLACEHOLDERS set. The interceptor only supports eight documented placeholders; any other token-shaped string is rejected as an IllegalArgumentException when the message is set.","triggerScenarios":"Calling setEnterMessage, setExitMessage, or setExceptionMessage with a string containing a token like '$[method]', '$[return]', '$[time]', or '$[result]'. The regex PATTERN matches any $[letters]+ token, then ALLOWED_PLACEHOLDERS membership is checked - typos and unsupported names both fail.","commonSituations":"Misspelling a supported placeholder ($[returnValue] written as $[return]). Assuming a placeholder exists that does not (e.g. $[threadName]). Copying a template from another logging library's syntax into CustomizableTraceInterceptor.","solutions":["Use only the documented placeholders: $[methodName], $[targetClassName], $[targetClassShortName], $[returnValue], $[argumentTypes], $[arguments], $[exception], $[invocationTime].","Correct the typo - e.g. '$[return]' -> '$[returnValue]'.","Mind per-message restrictions: enterMessage cannot contain $[returnValue], $[exception], or $[invocationTime]; these are checked separately after the placeholder check.","Reference the PLACEHOLDER_* public constants when building the message string to avoid typos."],"exampleFix":"// before\ntraceInterceptor.setExitMessage(\"Done $[method] in $[time] returned $[return]\");\n\n// after\ntraceInterceptor.setExitMessage(\n    \"Done $[methodName] in $[invocationTime] returned $[returnValue]\");","handlingStrategy":"validation","validationCode":"import org.springframework.aop.interceptor.CustomizableTraceInterceptor;\nstatic void validateTemplate(String msg) {\n    java.util.regex.Matcher m =\n        java.util.regex.Pattern.compile(\"\\\\$\\\\[\\\\p{Alpha}+]\").matcher(msg);\n    while (m.find()) {\n        if (!CustomizableTraceInterceptor.ALLOWED_PLACEHOLDERS.contains(m.group()))\n            throw new IllegalArgumentException(\"Bad placeholder \" + m.group());\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build message templates using the PLACEHOLDER_* constants, not raw strings.","Cross-check each token against the javadoc list of eight placeholders.","Watch per-message restrictions (e.g. no $[returnValue] in enterMessage)."],"tags":["spring-aop","tracing","configuration","template"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}