quarkusio/quarkus · error · IllegalArgumentException

Illegal end of expression

Error message

Illegal end of expression

What it means

The parser rejects a '$' at the very end of a ClientHeaderParam value because ${ requires a property name and a closing brace; a trailing '$' can never form a valid expression. It fails fast at build time with IllegalArgumentException wrapped with the offending input.

Source

Thrown at extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java:1179

            this.input = Objects.requireNonNull(input);
            this.sourceMethod = sourceMethod;
        }

        // this is a pretty naive implementation, but it suffices for what we are trying to do
        List<Node> parse() {
            int i = 0;
            int configStart = -1;
            int accessibleStart = -1;
            int verbatimStart = -1;
            List<Node> nodes = new ArrayList<>();
            while (i < input.length()) {
                char c = input.charAt(i);
                if (c == '$') {
                    if ((configStart != -1) || (accessibleStart != -1)) {
                        throw new IllegalArgumentException(createEffectiveErrorMessage("Cannot mix expressions"));
                    }
                    if (i == input.length() - 1) {
                        throw new IllegalArgumentException(createEffectiveErrorMessage("Illegal end of expression"));
                    }
                    if (input.charAt(i + 1) != '{') {
                        throw new IllegalArgumentException(createEffectiveErrorMessage("'$' must always be followed by '{'"));
                    }
                    if (verbatimStart != -1) {
                        nodes.add(new Verbatim(input.substring(verbatimStart, i)));
                    }
                    i += 2;
                    configStart = i;
                    verbatimStart = -1;
                } else if (c == '{') {
                    if ((configStart != -1) || (accessibleStart != -1)) {
                        throw new IllegalArgumentException(createEffectiveErrorMessage("Cannot mix expressions"));
                    }
                    if (i == input.length() - 1) {
                        throw new IllegalArgumentException(createEffectiveErrorMessage("Illegal end of expression"));
                    }
                    if (verbatimStart != -1) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Complete the expression: replace trailing '$' with a full ${property} form
  2. Remove the stray '$' if it was accidental
  3. If a literal '$' is needed as verbatim text, ensure it is not the last character or restructure (the naive parser treats a lone '$' mid-text followed by '{' as an expression start; a trailing '$' is always invalid)

Example fix

// before
@ClientHeaderParam(name="X-Price", value="100$")

// after
@ClientHeaderParam(name="X-Price", value="USD 100")
Defensive patterns

Strategy: validation

Validate before calling

String v = "apikey$";
if (v.trim().endsWith("$")) {
    throw new IllegalArgumentException("ClientHeaderParam value cannot end with a bare '$'");
}

Prevention

When it happens

Trigger: Annotation value ending with a dangling '$', e.g. @ClientHeaderParam(name="X", value="apikey$") — often after accidental truncation or an intended literal '$' unescaped.

Common situations: Copy-paste truncation of long header values, or attempting to embed a literal dollar sign (e.g. currency) at the end of a header value.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/06bd714c665f9db3. Report an issue: GitHub.