spring-projects/spring-framework · error · IllegalArgumentException

Placeholder [{match}] is not valid

Error message

Placeholder [{match}] is not valid

What it means

checkForInvalidPlaceholders throws IllegalArgumentException at setter time when setEnterMessage/setExitMessage/setExceptionMessage contains a $[...] token that is not one of the eight allowed placeholders. The valid set is fixed (methodName, targetClassName, targetClassShortName, returnValue, argumentTypes, arguments, exception, invocationTime); any other match of the regex $\[\p{Alpha}+] is rejected.

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 e8729d0438)

Solutions

  1. Use only the documented placeholder constants (e.g. $[methodName], $[targetClassName], $[returnValue]).
  2. Respect per-message restrictions: enterMessage cannot use $[returnValue], $[exception], or $[invocationTime].
  3. Reference CustomizableTraceInterceptor.PLACEHOLDER_* constants instead of hardcoding strings.

Example fix

// before
interceptor.setEnterMessage("Entering $[method] on $[target]");

// after
interceptor.setEnterMessage(
    "Entering " + CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME +
    " on " + CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_NAME);
Defensive patterns

Strategy: validation

Validate before calling

static final Set<String> ALLOWED = CustomizableTraceInterceptor.ALLOWED_PLACEHOLDERS;
void validate(String msg) {
    Matcher m = Pattern.compile("\\$\\[\\p{Alpha}+]").matcher(msg);
    while (m.find()) {
        if (!ALLOWED.contains(m.group())) {
            throw new IllegalArgumentException("bad placeholder: " + m.group());
        }
    }
}

Prevention

When it happens

Trigger: Calling interceptor.setEnterMessage("Entering $[method] for $[target]") where $[method] and $[target] are not recognised placeholders (the real names are $[methodName] and $[targetClassName]).

Common situations: Misspelling a placeholder; copying an example from an outdated tutorial; using a $[var] shell-style variable that happens to match the regex.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/a63147d9a998af8a.json. Report an issue: GitHub.