OpenFeign/feign · error · EncodeException
Failure encoding object into query map
Error message
Failure encoding object into query map
What it means
FieldQueryMapEncoder reads an object's fields reflectively (field.get(object)) to build a query-parameter map. When a field is not accessible to the encoder, the IllegalAccessException is wrapped in EncodeException with this message, failing request encoding.
Solutions
- Make the @QueryMap object's class public (a public class with package-private fields is fine for field access); rethrowing happens on Field.get so class accessibility is key
- Inspect the wrapped cause via EncodeException.getCause() to identify the offending field/class
- Catch EncodeException around request execution and log it before retrying
- Alternatively switch to BeanQueryMapEncoder or an explicit Map<String, Object> for the query parameters
Example fix
// before
// package-private class used as @QueryMap
class SearchParams { public String q; public int limit; }
// after
public class SearchParams { public String q; public int limit; } // public class so Field.get succeeds Defensive patterns
Strategy: try-catch
Validate before calling
if (!Modifier.isPublic(params.getClass().getModifiers())) {
throw new IllegalStateException("@QueryMap object class must be public: " + params.getClass());
} Type guard
boolean isFieldAccessible(Object o) {
return o != null && Modifier.isPublic(o.getClass().getModifiers());
} Try / catch
try {
api.search(params);
} catch (EncodeException e) {
throw new IllegalArgumentException("query map field not readable: " + e.getCause(), e);
} Prevention
- Declare @QueryMap objects as public top-level or public static nested classes
- Check getCause() (IllegalAccessException) to identify the inaccessible field
- Prefer Map<String, Object> or BeanQueryMapEncoder when class accessibility is uncertain
When it happens
Trigger: Encoding a @QueryMap object whose fields cannot be read via Field.get — e.g., a non-public class with public fields, or fields made inaccessible under restrictive access/module checks — during Feign request creation.
Common situations: Using package-private or private classes as @QueryMap objects (field.get fails even for public fields because the declaring class is not accessible); JPMS strong encapsulation hiding the class; field values themselves never throw, so the cause is almost always IllegalAccessException.
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
- Failure encoding object into query map
- 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/00cf007e076c2c1a.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/feign/querymap/FieldQueryMapEncoder.java:65
ObjectParamMetadata metadata =
classToMetadata.computeIfAbsent(object.getClass(), ObjectParamMetadata::parseObjectType);
return metadata.objectFields.stream()
.map(field -> this.FieldValuePair(object, field))
.filter(fieldObjectPair -> fieldObjectPair.right.isPresent())
.collect(Collectors.toMap(this::fieldName, fieldObjectPair -> fieldObjectPair.right.get()));
}
private String fieldName(Pair<Field, Optional<Object>> pair) {
Param alias = pair.left.getAnnotation(Param.class);
return alias != null ? alias.value() : pair.left.getName();
}
private Pair<Field, Optional<Object>> FieldValuePair(Object object, Field field) {
try {
return Pair.pair(field, Optional.ofNullable(field.get(object)));
} catch (IllegalAccessException e) {
throw new EncodeException("Failure encoding object into query map", e);
}
}
private static class ObjectParamMetadata {
private final List<Field> objectFields;
private ObjectParamMetadata(List<Field> objectFields) {
this.objectFields = Collections.unmodifiableList(objectFields);
}
private static ObjectParamMetadata parseObjectType(Class<?> type) {
List<Field> allFields = new ArrayList();
for (Class currentClass = type;
currentClass != null;
currentClass = currentClass.getSuperclass()) {
Collections.addAll(allFields, currentClass.getDeclaredFields());View on GitHub (pinned to e2a1e27560)