quarkusio/quarkus · error · IllegalArgumentException
Invalid expression: ${expression}
Error message
Invalid expression: ${expression} What it means
ConfigUtils.interpolate resolves MicroProfile config property placeholders of the form ${name} inside REST client values (URLs, URIs, proxies). This error is thrown when the expression contains ${ without a matching closing }, so the library cannot determine the property name. It is a syntax validation of the interpolated string.
Source
Thrown at extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/ConfigUtils.java:29
static final String PREFIX = "${";
static final String SUFFIX = "}";
/**
* Interpolates the given expression. The expression is expected to be in the form of ${config.property.name}.
*
* @param expression the expression to interpolate
* @param required whether the expression is required to be present in the configuration
* @return null if the resulting expression is empty, otherwise the interpolated expression
*/
@SuppressWarnings("unused")
public static String interpolate(String expression, boolean required) {
StringBuilder sb = new StringBuilder(expression);
int idx;
while ((idx = sb.lastIndexOf(PREFIX)) > -1) {
int endIdx = sb.indexOf(SUFFIX, idx);
if (endIdx < 0) {
throw new IllegalArgumentException("Invalid expression: " + expression);
}
String configValue = getConfigValue(sb.substring(idx, endIdx + 1), required);
// If no value is found, we return null directly
if (configValue == null) {
return null;
}
sb.replace(idx, endIdx + 1, configValue);
}
if (sb.length() == 0) {
return null;
}
return sb.toString();
}
/**
* Obtains the value of the {@param configProperty} expression. This expressions MUST be in the form of ${...}
*/
public static String getConfigValue(String configProperty, boolean required) {View on GitHub (pinned to e1c734241f)
Solutions
- Add the missing closing brace '}' to the property reference
- Escape or remove the stray '${' if no config substitution is intended
- Verify the resolved value at build time by logging the raw property from application.properties
Example fix
# before
quarkus.rest-client.svc.url=${API_HOST/api
# after
quarkus.rest-client.svc.url=${API_HOST}:8080/api Defensive patterns
Strategy: validation
Validate before calling
static void validateInterpolation(String expr) {
int open = 0;
for (int i = 0; i < expr.length(); i++) {
char c = expr.charAt(i);
if (c == '$' && i + 1 < expr.length() && expr.charAt(i + 1) == '{') open++;
else if (c == '}') open--;
if (open < 0) throw new IllegalArgumentException("Unmatched } in: " + expr);
}
if (open != 0) throw new IllegalArgumentException("Unclosed ${ in: " + expr);
} Try / catch
try {
String url = ConfigUtils.interpolate(rawUrl, true);
} catch (IllegalArgumentException e) {
throw new ConfigurationException("Malformed ${} expression in rest-client config: " + rawUrl, e);
} Prevention
- Always close ${...} references in application.properties
- Log raw config values in a startup health check to spot malformed expressions early
- Avoid hand-concatenating ${} strings; use config property expansion tooling
When it happens
Trigger: Passing a value to a rest client builder (e.g. baseUri/url/proxy config from application.properties or @RegisterRestClient config) that contains '${' with no '}' closing brace, such as a truncated or typo'd property reference.
Common situations: Typo in application.properties like quarkus.rest-client.myservice.url=${MY_URL; accidentally truncated string interpolation in code generation; shell/env placeholder copied verbatim without a closing brace.
Related errors
- Unable to find provider for REST Client '${class}' with name
- Multiple providers found for REST Client '${class}'. Please
- Failed to find value for config property %s in application c
- Failed to convert value for property ${property} to String
- The configuration ${clazz} must be an interface annotated wi
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4a5a904f8e726945.
Report an issue: GitHub.