{"record":{"id":"c23f54d0729eb454","repo":"OpenFeign/feign","slug":"value-expanded-does-not-match-the-expression-pat","errorCode":null,"errorMessage":"Value {expanded} does not match the expression pattern: {pattern}","messagePattern":"Value (.+?) does not match the expression pattern: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/feign/template/Expressions.java","lineNumber":205,"sourceCode":"        if (optional.isPresent()) {\n          expanded.append(this.expand(optional.get(), encode));\n        } else {\n          if (!this.nameRequired) {\n            return null;\n          }\n          expanded.append(this.encode(this.getName())).append(\"=\");\n        }\n      } else {\n        if (this.nameRequired) {\n          expanded.append(this.encode(this.getName())).append(\"=\");\n        }\n        expanded.append((encode) ? encode(variable) : variable);\n      }\n\n      /* return the string value of the variable */\n      String result = expanded.toString();\n      if (!this.matches(result)) {\n        throw new IllegalArgumentException(\n            \"Value \" + expanded + \" does not match the expression pattern: \" + this.getPattern());\n      }\n      return result;\n    }\n\n    protected String expandIterable(Iterable<?> values) {\n      StringBuilder result = new StringBuilder();\n      for (Object value : values) {\n        if (value == null) {\n          /* skip */\n          continue;\n        }\n\n        /* expand the value */\n        String expanded = this.encode(value);\n        if (expanded.isEmpty()) {\n          /* always append the separator */\n          result.append(this.separator);","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/OpenFeign/feign/blob/e2a1e27560a1e68840c34f031afca88b36096e30/core/src/main/java/feign/template/Expressions.java#L187-L223","documentation":"After expanding a template expression variable, Feign validates the resulting value against the variable's declared pattern (the 'name:pattern' syntax inside the expression, e.g. {id:\\d+}). If the expanded value does not match that pattern, the expansion is rejected with this IllegalArgumentException. This guards against producing invalid URIs when a constrained variable receives a non-conforming value.","triggerScenarios":"Declaring an expression with a regex constraint like {userId:[0-9]+} and calling resolve/expand with a value that fails the regex (e.g. 'abc' for [0-9]+); value contains characters the pattern excludes; iterable expansion producing a joined value that violates the pattern.","commonSituations":"Passing null-ish 'null' string, empty string, or URL-encoded values that no longer match the declared pattern; changing a variable's type/format upstream without updating the interface annotation; copy-pasted pattern from another endpoint no longer fitting the data.","solutions":["Fix the value passed to the variable so it conforms to the declared pattern.","Loosen or correct the pattern in the template/annotation (e.g. {id:.+} for permissive matching).","Pre-validate the value in client code against the same pattern before expanding.","Remove the pattern constraint entirely ({id} instead of {id:\\d+}) if no constraint is needed."],"exampleFix":"// before\n@RequestLine(\"GET /users/{id:\\\\d+}\")\nUser get(String id); // called with get(\"abc\") -> pattern mismatch\n// after\n@RequestLine(\"GET /users/{id}\")\nUser get(String id); // or pass a numeric id","handlingStrategy":"validation","validationCode":"Pattern p = Pattern.compile(\"\\\\d+\");\nif (userId == null || !p.matcher(userId).matches()) {\n  throw new IllegalArgumentException(\"userId must match the declared template pattern\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return feignClient.get(userId);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"does not match the expression pattern\")) {\n    throw new InvalidUserIdException(userId, e);\n  }\n  throw e;\n}","preventionTips":["Keep template patterns in sync with the actual data format of the variables.","Pre-validate values against the same regex used in the template before calling the client.","Prefer unconstrained expressions ({id}) unless a constraint is genuinely needed.","Watch for encoded values that change the string so it no longer matches the pattern."],"tags":["feign","uri-template","regex","pattern-mismatch"],"backgroundTag":"invalid-argument-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"}