OpenFeign/feign · error · RuntimeException

Unable to enrich

Error message

Unable to enrich ${target}

What it means

Thrown by Capability.invoke when reflectively invoking a Capability's enrich method on the target object throws IllegalAccessException, IllegalArgumentException, or InvocationTargetException. The user-provided Capability itself failed while enriching a component, so the builder aborts with the underlying cause attached.

Solutions

  1. Read the cause of this RuntimeException — it is the real exception thrown inside your Capability's enrich method
  2. Fix the enrich override to be null-safe and to return the original target when it cannot enrich (return target as fallback)
  3. Wrap your enrichment logic in try/catch inside the Capability and degrade gracefully instead of throwing

Example fix

// before
@Override
public Client enrich(Client client) {
  return new TracingClient((MonitoringClient) client); // ClassCastException for other impls
}
// after
@Override
public Client enrich(Client client) {
  if (client instanceof MonitoringClient) {
    return new TracingClient((MonitoringClient) client);
  }
  return client; // fallback: leave unenriched
}
Defensive patterns

Strategy: try-catch

Validate before calling

try {
  Client enriched = capability.enrich(existingClient);
} catch (Exception e) {
  throw new IllegalStateException("Capability enrichment is not safe", e);
}

Try / catch

try { Feign.builder().addCapability(cap).build(); }
catch (RuntimeException e) { if (e.getMessage().startsWith("Unable to enrich ")) { /* see e.getCause() */ } }

Prevention

When it happens

Trigger: A Capability's enrich override throws at runtime (InvocationTargetException) — e.g. NPE inside the enrichment logic; or the method is invoked with a target of an unexpected type.

Common situations: Capability enrichment code that assumes non-null wrapped components or a specific client implementation; initialization code in a Capability that fails in a restricted environment (e.g. missing config, missing dependency).

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/fa0ce0fdceb262c3. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/feign/Capability.java:70

        .reduce(
            componentToEnrich,
            (target, capability) -> invoke(target, capability, capabilityToEnrich),
            (component, enrichedComponent) -> enrichedComponent);
  }

  static Object invoke(Object target, Capability capability, Class<?> capabilityToEnrich) {
    return Arrays.stream(capability.getClass().getMethods())
        .filter(method -> method.getName().equals("enrich"))
        .filter(method -> method.getReturnType().isAssignableFrom(capabilityToEnrich))
        .findFirst()
        .map(
            method -> {
              try {
                return method.invoke(capability, target);
              } catch (IllegalAccessException
                  | IllegalArgumentException
                  | InvocationTargetException e) {
                throw new RuntimeException("Unable to enrich " + target, e);
              }
            })
        .orElse(target);
  }

  default Client enrich(Client client) {
    return client;
  }

  default AsyncClient<Object> enrich(AsyncClient<Object> client) {
    return client;
  }

  default Retryer enrich(Retryer retryer) {
    return retryer;
  }

  default RequestInterceptor enrich(RequestInterceptor requestInterceptor) {

View on GitHub (pinned to e2a1e27560)