spring-projects/spring-framework · error · IllegalArgumentException
Placeholder [ ] is not valid
Error message
Placeholder [{match}] is not valid What it means
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.
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.
Example fix
// before
traceInterceptor.setExitMessage("Done $[method] in $[time] returned $[return]");
// after
traceInterceptor.setExitMessage(
"Done $[methodName] in $[invocationTime] returned $[returnValue]"); Defensive patterns
Strategy: validation
Validate before calling
import org.springframework.aop.interceptor.CustomizableTraceInterceptor;
static void validateTemplate(String msg) {
java.util.regex.Matcher m =
java.util.regex.Pattern.compile("\\$\\[\\p{Alpha}+]").matcher(msg);
while (m.find()) {
if (!CustomizableTraceInterceptor.ALLOWED_PLACEHOLDERS.contains(m.group()))
throw new IllegalArgumentException("Bad placeholder " + m.group());
}
} Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Advice must be declared inside an aspect type: Offending…
- Advice object [ ] is neither a supported subinterface of…
- AdvisorAutoProxyCreator requires a…
- 'argumentNames' property of AbstractAspectJAdvice contains…
- is not an @AspectJ aspect
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/a63147d9a998af8a.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/interceptor/CustomizableTraceInterceptor.java:397
String[] argumentTypeShortNames = new String[argumentTypes.length];
for (int i = 0; i < argumentTypeShortNames.length; i++) {
argumentTypeShortNames[i] = ClassUtils.getShortName(argumentTypes[i]);
}
matcher.appendReplacement(output,
Matcher.quoteReplacement(StringUtils.arrayToCommaDelimitedString(argumentTypeShortNames)));
}
/**
* Checks to see if the supplied {@code String} has any placeholders
* that are not specified as constants on this class and throws an
* {@code IllegalArgumentException} if so.
*/
private static void checkForInvalidPlaceholders(String message) throws IllegalArgumentException {
Matcher matcher = PATTERN.matcher(message);
while (matcher.find()) {
String match = matcher.group();
if (!ALLOWED_PLACEHOLDERS.contains(match)) {
throw new IllegalArgumentException("Placeholder [" + match + "] is not valid");
}
}
}
}
View on GitHub (pinned to 69bf83ad71)