OpenFeign/feign · error · IllegalStateException
Cannot generate exception - check constructor parameter…
Error message
Cannot generate exception - check constructor parameter types (are headers Map<String,Collection<String>> or is something causing an exception on construction?)
What it means
Thrown by ExceptionGenerator.validateGeneratorCanBeUsedToGenerateExceptions during build() as a dry-run sanity check: it invokes the custom exception's constructor against a test response, and any exception escaping the constructor triggers this error. It means the exception class's constructor signature or constructor body is incompatible with the arguments Feign supplies (status, body, headers Map<String,Collection<String>>).
Solutions
- Fix the constructor body so it tolerates null/empty body and raw non-JSON content without throwing
- Match constructor parameter types exactly to supported ones: (Response), (String body), (int status), (Map<String,Collection<String>> headers), or combinations in supported orders
- Inspect the cause attached to this IllegalStateException — it contains the real exception thrown inside your constructor
- Simplify to a constructor accepting only (int status, String body) if unsure
Example fix
// before
public class ApiError extends RuntimeException {
public ApiError(int status, Map<String, String> headers, String body) {
super(parse(body).get("message")); // throws on empty body
}
}
// after
public class ApiError extends RuntimeException {
public ApiError(int status, Map<String, Collection<String>> headers, String body) {
super(body != null ? extractMessage(body) : ("HTTP " + status));
}
} Defensive patterns
Strategy: validation
Validate before calling
// unit-test your exception constructor the way Feign does new ApiError(500, null, Collections.<String, Collection<String>>emptyMap());
Try / catch
try { api.call(); } catch (IllegalStateException e) {
if (e.getCause() != null) { log.error("constructor threw", e.getCause()); }
} Prevention
- Never let the exception constructor throw — guard all parsing and validation
- Use supported parameter types: int status, String body, Map<String,Collection<String>> headers, Response
- Handle null body and non-JSON error payloads in the constructor
- Write a test invoking the constructor with an empty response
When it happens
Trigger: An exception class annotated with @FeignExceptionConstructor whose constructor throws during construction (e.g. NPE parsing the body string), or whose parameter types force an unconvertible argument (e.g. constructor takes int status but receives a value that cannot be coerced, or wrong headers generic type).
Common situations: Constructor parses the raw body with JSON parsing that fails on empty/HTML bodies; headers declared as Map<String,String> instead of Map<String,Collection<String>>; constructor validation (Objects.requireNonNull / custom precondition) rejects the test response's null body.
Related errors
- Too many constructors marked with @FeignExceptionConstructor
- Cannot find any suitable constructor in class
- Cannot access constructor
- Cannot instantiate exception with constructor
- Cannot invoke constructor
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/3ce937147ecdf1f4.
Report an issue: GitHub.
Appendix: source
Thrown at annotation-error-decoder/src/main/java/feign/error/ExceptionGenerator.java:198
ExceptionGenerator generator =
new ExceptionGenerator(
bodyIndex,
requestIndex,
headerMapIndex,
numOfParams,
bodyType,
exceptionType,
responseBodyDecoder);
validateGeneratorCanBeUsedToGenerateExceptions(generator);
return generator;
}
private void validateGeneratorCanBeUsedToGenerateExceptions(ExceptionGenerator generator) {
try {
generator.createException(TEST_RESPONSE);
} catch (Exception e) {
throw new IllegalStateException(
"Cannot generate exception - check constructor parameter types (are headers"
+ " Map<String,Collection<String>> or is something causing an exception on"
+ " construction?)",
e);
}
}
private Constructor<? extends Exception> getConstructor(
Class<? extends Exception> exceptionClass) {
Constructor<? extends Exception> preferredConstructor = null;
for (Constructor<?> constructor : exceptionClass.getConstructors()) {
FeignExceptionConstructor exceptionConstructor =
constructor.getAnnotation(FeignExceptionConstructor.class);
if (exceptionConstructor == null) {
continue;
}
Class<?>[] parameterTypes = constructor.getParameterTypes();View on GitHub (pinned to e2a1e27560)