{"record":{"id":"2ba5c2244debdef1","repo":"quarkusio/quarkus","slug":"must-always-be-followed-by","errorCode":null,"errorMessage":"'$' must always be followed by '{'","messagePattern":"'\\$' must always be followed by '\\{'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java","lineNumber":1182,"sourceCode":"\n        // this is a pretty naive implementation, but it suffices for what we are trying to do\n        List<Node> parse() {\n            int i = 0;\n            int configStart = -1;\n            int accessibleStart = -1;\n            int verbatimStart = -1;\n            List<Node> nodes = new ArrayList<>();\n            while (i < input.length()) {\n                char c = input.charAt(i);\n                if (c == '$') {\n                    if ((configStart != -1) || (accessibleStart != -1)) {\n                        throw new IllegalArgumentException(createEffectiveErrorMessage(\"Cannot mix expressions\"));\n                    }\n                    if (i == input.length() - 1) {\n                        throw new IllegalArgumentException(createEffectiveErrorMessage(\"Illegal end of expression\"));\n                    }\n                    if (input.charAt(i + 1) != '{') {\n                        throw new IllegalArgumentException(createEffectiveErrorMessage(\"'$' must always be followed by '{'\"));\n                    }\n                    if (verbatimStart != -1) {\n                        nodes.add(new Verbatim(input.substring(verbatimStart, i)));\n                    }\n                    i += 2;\n                    configStart = i;\n                    verbatimStart = -1;\n                } else if (c == '{') {\n                    if ((configStart != -1) || (accessibleStart != -1)) {\n                        throw new IllegalArgumentException(createEffectiveErrorMessage(\"Cannot mix expressions\"));\n                    }\n                    if (i == input.length() - 1) {\n                        throw new IllegalArgumentException(createEffectiveErrorMessage(\"Illegal end of expression\"));\n                    }\n                    if (verbatimStart != -1) {\n                        nodes.add(new Verbatim(input.substring(verbatimStart, i)));\n                    }\n                    i++;","sourceCodeStart":1164,"sourceCodeEnd":1200,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java#L1164-L1200","documentation":"In ClientHeaderParam values, '$' only introduces configuration expressions in the ${property} form. A '$' followed by any character other than '{' (e.g. $token) is rejected at build time with IllegalArgumentException, since bare $name syntax is not supported.","triggerScenarios":"Values like \"$version\" or \"prefix-$value\" inside @ClientHeaderParam — a '$' not immediately followed by '{'.","commonSituations":"Habit from Spring/property-placeholder syntax ($key instead of ${key}), or template strings containing currency amounts like \"$100\".","solutions":["Use the full ${property} syntax: \"$value\" becomes \"${value}\"","Remove the '$' if it was meant as literal text","Move dollar-containing literal text so '$' is never directly followed by a non-'{' character, or use a method reference to produce the value"],"exampleFix":"// before\n@ClientHeaderParam(name=\"X-Build\", value=\"$buildId\")\n\n// after\n@ClientHeaderParam(name=\"X-Build\", value=\"${buildId}\")","handlingStrategy":"validation","validationCode":"String v = \"$buildId\";\nfor (int i = 0; i < v.length(); i++) {\n    if (v.charAt(i) == '$' && (i == v.length() - 1 || v.charAt(i + 1) != '{')) {\n        throw new IllegalArgumentException(\"'$' must be followed by '{': \" + v);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write config lookups as ${property}, never $property","Escape or remove literal '$' characters in header text","Search codebase for \"\\$[^{]\" in annotation values during code review"],"tags":["quarkus","rest-client","expression-parsing","syntax"],"backgroundTag":"expression-syntax-error","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}