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
- Read the cause of this RuntimeException — it is the real exception thrown inside your Capability's enrich method
- Fix the enrich override to be null-safe and to return the original target when it cannot enrich (return target as fallback)
- 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
- Keep enrich overrides side-effect-free and null-safe
- Return the original target when enrichment is not applicable
- Initialize Capability state lazily and defensively (missing config should not throw)
- Unit-test each Capability's enrich methods against multiple client/encoder implementations
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
- Unable to enrich field
- Cannot generate exception - check constructor parameter…
- Too many constructors marked with @FeignExceptionConstructor
- Cannot find any suitable constructor in class
- Cannot access constructor
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)