OpenFeign/feign · error · IllegalStateException

Cannot invoke constructor

Error message

Cannot invoke constructor

What it means

Thrown by MethodErrorHandler.createException when InvocationTargetException is raised: the exception's constructor itself threw an exception while Feign was building the error exception for a non-2xx response. The real failure is in the constructor body, available as the cause of this IllegalStateException.

Solutions

  1. Inspect the cause chain of this exception to find the constructor failure and make the constructor defensive about null/empty/malformed bodies
  2. Guard JSON parsing in the constructor with try/catch and fall back to the raw body or status code as the message
  3. Broaden the constructor to accept what error responses actually deliver rather than assuming a happy-path payload

Example fix

// before
public ApiError(String body) {
  super(new ObjectMapper().readTree(body).get("message").asText()); // throws on HTML/empty
}
// after
public ApiError(String body) {
  super(safeMessage(body));
}
private static String safeMessage(String body) {
  try { return new ObjectMapper().readTree(body).get("message").asText(); }
  catch (Exception e) { return body == null ? "" : body; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// exercise the constructor with worst-case inputs before wiring it
Arrays.asList(null, "", "<html>err</html>").forEach(b -> {
  try { new ApiError(500, b); } catch (Exception e) { throw new AssertionError("ctor not defensive", e); }
});

Try / catch

try { api.call(); }
catch (FeignException e) { /* HTTP-level */ }
catch (IllegalStateException e) {
  if ("Cannot invoke constructor".equals(e.getMessage())) {
    Throwable real = e.getCause().getCause(); // exception thrown by your constructor
  }
}

Prevention

When it happens

Trigger: Exception constructor that parses the response body (e.g. JSON deserialization) and throws on unexpected content; constructor preconditions (e.g. Objects.requireNonNull on body or a header) that fail for the actual error response received from the server.

Common situations: Server returns an HTML error page or empty body where the constructor expects JSON; a required header is absent on the error response; NPE in constructor logic for status codes not anticipated.

Related errors


AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10). Data as JSON: /api/errors/40dd02aeb53f2bdc. Report an issue: GitHub.

Appendix: source

Thrown at annotation-error-decoder/src/main/java/feign/error/MethodErrorHandler.java:60

  private ExceptionGenerator getConstructorDefinition(Response response) {
    if (methodLevelExceptionsByCode.containsKey(response.status())) {
      return methodLevelExceptionsByCode.get(response.status());
    }
    if (classLevelExceptionsByCode.containsKey(response.status())) {
      return classLevelExceptionsByCode.get(response.status());
    }
    return defaultException;
  }

  protected Exception createException(ExceptionGenerator constructorDefinition, Response response) {
    try {
      return constructorDefinition.createException(response);
    } catch (IllegalAccessException e) {
      throw new IllegalStateException("Cannot access constructor", e);
    } catch (InstantiationException e) {
      throw new IllegalStateException("Cannot instantiate exception with constructor", e);
    } catch (InvocationTargetException e) {
      throw new IllegalStateException("Cannot invoke constructor", e);
    } catch (NoSuchMethodException e) {
      throw new IllegalStateException("Constructor does not exist", e);
    }
  }
}

View on GitHub (pinned to e2a1e27560)