OpenFeign/feign · error · IllegalStateException

Too many constructors marked with @FeignExceptionConstructor

Error message

Too many constructors marked with @FeignExceptionConstructor

What it means

Thrown by ExceptionGenerator.getConstructor when more than one constructor of the exception class is annotated with @FeignExceptionConstructor. The annotation designates a single preferred constructor, so multiple annotated constructors make the choice ambiguous and the library refuses to guess.

Solutions

  1. Keep @FeignExceptionConstructor on exactly one constructor and remove it from the others
  2. If both constructors are needed, make one delegate to the annotated one via this(...) chaining instead of annotating both

Example fix

// before
public class ApiError extends RuntimeException {
  @FeignExceptionConstructor
  public ApiError(int status, String body) { ... }

  @FeignExceptionConstructor
  public ApiError(String body) { this(0, body); }
}
// after
public class ApiError extends RuntimeException {
  @FeignExceptionConstructor
  public ApiError(int status, String body) { ... }

  public ApiError(String body) { this(0, body); }
}
Defensive patterns

Strategy: validation

Validate before calling

long marked = Arrays.stream(ApiError.class.getConstructors())
    .filter(c -> c.isAnnotationPresent(FeignExceptionConstructor.class)).count();
if (marked > 1) throw new IllegalStateException("Only one @FeignExceptionConstructor allowed");

Try / catch

try { Feign.builder().errorDecoder(decoder).build(); }
catch (IllegalStateException e) { if (e.getMessage().contains("Too many constructors")) { ... } }

Prevention

When it happens

Trigger: Annotating two or more constructors of the same exception class with @FeignExceptionConstructor, often after adding an overloaded constructor and annotating both.

Common situations: Adding a convenience constructor for tests and marking both with the annotation; merging branches where each added an annotated constructor.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at annotation-error-decoder/src/main/java/feign/error/ExceptionGenerator.java:223

    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();
        if (parameterTypes.length == 0) {
          continue;
        }
        if (preferredConstructor == null) {
          preferredConstructor = (Constructor<? extends Exception>) constructor;
        } else {
          throw new IllegalStateException(
              "Too many constructors marked with @FeignExceptionConstructor");
        }
      }

      if (preferredConstructor == null) {
        try {
          return exceptionClass.getConstructor();
        } catch (NoSuchMethodException e) {
          throw new IllegalStateException(
              "Cannot find any suitable constructor in class ["
                  + exceptionClass.getName()
                  + "] - did you forget to mark one with @FeignExceptionConstructor or at least"
                  + " have a public default constructor?",
              e);
        }
      }
      return preferredConstructor;
    }

View on GitHub (pinned to e2a1e27560)