OpenFeign/feign · error · IllegalStateException

Cannot access constructor

Error message

Cannot access constructor

What it means

Thrown by MethodErrorHandler.createException (wrapped in IllegalStateException) when reflection reports IllegalAccessException while instantiating the mapped exception for an error response. The constructor exists but is not accessible from Feign's reflection code, e.g. it is not public or the class is non-public/nested.

Solutions

  1. Make the exception class public and static (top-level or static nested) and its @FeignExceptionConstructor constructor public
  2. If the constructor must stay non-public, ensure the class is in the same package as your decoder configuration or open the package in module-info.java
  3. Catch IllegalStateException around the Feign call and log the cause for the underlying IllegalAccessException

Example fix

// before
class ApiError extends RuntimeException { // package-private
  ApiError(int status, String body) { ... }
}
// after
public class ApiError extends RuntimeException {
  public ApiError(int status, String body) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

int mods = ApiError.class.getModifiers();
if (!Modifier.isPublic(mods) || Modifier.isAbstract(mods) ||
    ApiError.class.isMemberClass() && !Modifier.isStatic(mods)) {
  throw new IllegalStateException("Exception class must be public, static, non-abstract");
}
if (!Modifier.isPublic(ctor.getModifiers())) throw new IllegalStateException("Constructor must be public");

Try / catch

try { api.call(); } catch (IllegalStateException e) {
  if ("Cannot access constructor".equals(e.getMessage()) && e.getCause() instanceof IllegalAccessException) { ... }
}

Prevention

When it happens

Trigger: @FeignExceptionConstructor is on a non-public constructor; the exception class is a package-private or inner (non-static nested) class so its public constructors are still not accessible reflectively without setAccessible.

Common situations: Defining the custom exception as a non-static inner class of the client interface; making the constructor package-private for testing; module-system (JPMS) restrictions hiding the package.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

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

    ExceptionGenerator constructorDefinition = getConstructorDefinition(response);
    return createException(constructorDefinition, response);
  }

  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)