{"record":{"id":"fe2a0d1d0d4fddeb","repo":"OpenFeign/feign","slug":"an-expression-is-required","errorCode":null,"errorMessage":"an expression is required.","messagePattern":"an expression is required\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/feign/template/Expressions.java","lineNumber":81,"sourceCode":"   * A pattern for matching possible variable names.\n   *\n   * <p>This pattern accepts characters allowed in RFC 6570 Section 2.3 It also allows the\n   * characters feign has allowed in the past \"[]-$\"\n   *\n   * <p>The RFC specifies that a variable name followed by a ':' should be a max-length\n   * specification. Feign deviates from the rfc in that the ':' value modifier is used to mark a\n   * regular expression.\n   */\n  private static final Pattern VARIABLE_LIST_PATTERN =\n      Pattern.compile(\n          \"(([\\\\w-\\\\[\\\\]$]|%[0-9A-Fa-f]{2})(\\\\.?([\\\\w-\\\\[\\\\]$]|%[0-9A-Fa-f]{2}))*(:.*|\\\\*)?)(,(([\\\\w-\\\\[\\\\]$]|%[0-9A-Fa-f]{2})(\\\\.?([\\\\w-\\\\[\\\\]$]|%[0-9A-Fa-f]{2}))*(:.*|\\\\*)?))*\");\n\n  public static Expression create(final String value) {\n\n    /* remove the start and end braces */\n    final String expression = stripBraces(value);\n    if (expression == null || expression.isEmpty()) {\n      throw new IllegalArgumentException(\"an expression is required.\");\n    }\n\n    /*\n     * Check if the expression is too long. The limit is configurable through the\n     * \"feign.template.expression.maxLength\" system property and can be disabled by setting it to a\n     * non-positive value.\n     */\n    final int maxExpressionLength =\n        Integer.getInteger(MAX_EXPRESSION_LENGTH_PROPERTY, DEFAULT_MAX_EXPRESSION_LENGTH);\n    if (maxExpressionLength > 0 && expression.length() > maxExpressionLength) {\n      throw new IllegalArgumentException(\n          \"expression is too long. Max length: \" + maxExpressionLength);\n    }\n\n    /* create a new regular expression matcher for the expression */\n    String variableName = null;\n    String variablePattern = null;\n    String operator = null;","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/core/src/main/java/feign/template/Expressions.java#L63-L99","documentation":"Expressions.create() builds a URI-template expression from a braced token like {param}. After stripping the braces, if nothing remains (input was '{}', '{', '}' or empty), the input is not a valid expression and this IllegalArgumentException is thrown.","triggerScenarios":"Expanding or parsing a request template containing empty or brace-only tokens — e.g., a URI/path/query template containing '{}' or an unbalanced '{' or '}', or a template variable whose value/text resolves to empty braces.","commonSituations":"Typos in URI templates (stray braces); dynamically built template strings where a variable name was empty; concatenating path segments where an optional segment evaluated to nothing but left braces behind.","solutions":["Fix the template string to remove empty or malformed brace tokens (use a real variable name inside the braces)","Validate templates before passing them to Feign: check for '{}' or unmatched braces","Sanitize dynamically generated URI segments so optional/empty values drop the whole segment including braces","Catch IllegalArgumentException from Feign.builder().target(...)/template building to surface the bad template to the caller"],"exampleFix":"// before\nString path = \"/users/{}\"; // empty expression braces\nFeign.builder().target(Api.class, baseUrl); // throws at expansion\n// after\nString path = \"/users/{userId}\"; // named expression\n// or drop the segment when the value is absent:\nString resolved = userId == null ? \"/users\" : \"/users/{userId}\";","handlingStrategy":"validation","validationCode":"boolean validTemplate(String t) {\n  return t != null && !t.contains(\"{}\") && !t.matches(\".*\\{\\s*}.*\")\n      && t.chars().filter(c -> c == '{').count() == t.chars().filter(c -> c == '}').count();\n}","typeGuard":null,"tryCatchPattern":"try {\n  Feign.builder().target(Api.class, baseUrl);\n} catch (IllegalArgumentException e) {\n  if (\"an expression is required.\".equals(e.getMessage())) {\n    throw new IllegalStateException(\"template contains an empty brace expression\", e);\n  }\n  throw e;\n}","preventionTips":["Review URI templates for stray or empty braces","Drop whole path/query segments (including braces) when a value is optional and absent","Validate dynamically generated templates before building the client","Use named constants for templates instead of string concatenation"],"tags":["java","feign","uri-template","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"e2a1e27560a1e68840c34f031afca88b36096e30","analyzedAt":"2026-09-10T12:37:37.238Z","contentChangedAt":"2026-09-10T12:37:37.238Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}