OpenFeign/feign · error · EncodeException
${e.getMessage()}
Error message
${e.getMessage()} What it means
Feign's Jackson3Encoder wraps any JacksonException thrown while serializing the request body into a feign EncodeException, keeping the original Jackson message as the message. This means the ObjectMapper could not convert your object into JSON bytes for the given declared body type. It is a wrapper around an underlying serialization problem, not a network issue.
Solutions
- Read the wrapped cause (getCause()) - the JacksonException message names the exact property/class that failed
- Ensure the DTO has public getters or annotate/enable field visibility (mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY))
- Register needed Jackson modules (JavaTimeModule, Jdk8Module, etc.) on the ObjectMapper passed to Jackson3Encoder.create
- Verify the Type passed to encode matches the actual runtime object's type (avoid raw Object bodies)
- If serializing a third-party type, add a custom JsonSerializer or a mixin
Example fix
// before Feign.builder().encoder(new Jackson3Encoder(new ObjectMapper())); // after ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); Feign.builder().encoder(new Jackson3Encoder(mapper));
Defensive patterns
Strategy: try-catch
Validate before calling
// before encoding
if (object == null) throw new IllegalArgumentException("body must not be null");
if (!mapper.canSerialize(object.getClass())) {
throw new IllegalStateException("ObjectMapper cannot serialize " + object.getClass());
} Type guard
static boolean isEncodable(ObjectMapper mapper, Object o) {
return o != null && mapper.canSerialize(o.getClass());
} Try / catch
try {
encoder.encode(object, bodyType, template);
} catch (EncodeException e) {
Throwable root = e;
while (root.getCause() != null) root = root.getCause();
throw new IllegalStateException("Jackson serialization failed: " + root.getMessage(), e);
} Prevention
- Register all required Jackson modules (JavaTimeModule, Jdk8Module, ParameterNamesModule) at client construction
- Ensure DTOs have accessible getters or configure property visibility once on the shared ObjectMapper
- Avoid returning raw Object or unbounded generic types as request bodies
- Break cyclic object references or use @JsonManagedReference/@JsonBackReference
- Unit-test encoding of every DTO type before wiring the Feign client
When it happens
Trigger: Calling encode() on Jackson3Encoder when mapper.writerFor(javaType).writeValueAsBytes(object) throws a JacksonException - e.g. serializing an object with no accessible properties, an invalid JavaType derived from a generic Type, self-referential structures exceeding max depth, or a custom serializer throwing.
Common situations: Encoding POJOs without getters and without field visibility configured; using types like Object or raw generics that Jackson cannot resolve; missing jackson-databind serializers for third-party types (Instant, Optional without modules); cyclic object graphs.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- This form encoder has no delegate encoder, so it can only…
- Output closing error
- Writing file's ' ' content error
- Cannot convert to type
- Not supported type
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/4b86a028785dd7dd.
Report an issue: GitHub.
Appendix: source
Thrown at jackson3/src/main/java/feign/jackson3/Jackson3Encoder.java:61
JsonMapper.builder()
.changeDefaultPropertyInclusion(
incl -> incl.withValueInclusion(JsonInclude.Include.NON_NULL))
.enable(SerializationFeature.INDENT_OUTPUT)
.addModules(modules)
.build());
}
public Jackson3Encoder(JsonMapper mapper) {
this.mapper = mapper;
}
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) {
try {
JavaType javaType = mapper.getTypeFactory().constructType(bodyType);
template.body(mapper.writerFor(javaType).writeValueAsBytes(object), Util.UTF_8);
} catch (JacksonException e) {
throw new EncodeException(e.getMessage(), e);
}
}
@Override
public boolean canEncode(Object object, Type bodyType, RequestTemplate template) {
return Util.isJsonContentType(template);
}
}
View on GitHub (pinned to e2a1e27560)