apache/iceberg · error · RESTException
Failed to encode request body: %s
Error message
Failed to encode request body: %s
What it means
HTTPRequest.encodedBody serializes the request body: Maps go through RESTUtil.encodeFormData, other non-null objects through the shared Jackson ObjectMapper. If Jackson throws JsonProcessingException, the client wraps it in a RESTException with this message. It means the request payload could not be serialized to JSON before sending.
Source
Thrown at core/src/main/java/org/apache/iceberg/rest/HTTPRequest.java:109
/** Returns the raw, unencoded request body. */
@Nullable
@Value.Redacted
Object body();
/** Returns the encoded request body as a string. */
@Value.Lazy
@Nullable
@Value.Redacted
default String encodedBody() {
Object body = body();
if (body instanceof Map) {
return RESTUtil.encodeFormData((Map<?, ?>) body);
} else if (body != null) {
try {
return mapper().writeValueAsString(body);
} catch (JsonProcessingException e) {
throw new RESTException(e, "Failed to encode request body: %s", body);
}
}
return null;
}
/**
* Returns the {@link ObjectMapper} to use for encoding the request body. The default is {@link
* RESTObjectMapper#mapper()}.
*/
@Value.Default
default ObjectMapper mapper() {
return RESTObjectMapper.mapper();
}
@Value.Check
default void check() {
if (path().startsWith("/")) {
throw new RESTException(View on GitHub (pinned to 86d9c8fc54)
Solutions
- Send Iceberg's REST request types (e.g. RegisterTableRequest, UpdateNamespacePropertiesRequest) instead of ad-hoc objects.
- Inspect the chained JsonProcessingException cause to find the offending property and fix or exclude it (@JsonIgnore-style exclusion in your own mapper-compatible type).
- Ensure body getters never throw and the object has no cyclic references.
- If sending a form, pass a Map so it is encoded as form data instead of JSON.
Example fix
// before
request.withBody(myDomainObjectWithCycles);
// after
request.withBody(RegisterTableRequest.builder()
.name(tableName)
.location(location)
.build()); Defensive patterns
Strategy: type-guard
Type guard
static boolean jsonSerializable(Object body) {
try {
RESTObjectMapper.mapper().writeValueAsString(body);
return true;
} catch (JsonProcessingException e) {
return false;
}
} Try / catch
try {
request.withBody(body);
} catch (RESTException e) {
if (e.getMessage().startsWith("Failed to encode request body")) {
// inspect e.getCause() for the offending property; use a REST request type
}
throw e;
} Prevention
- Use Iceberg REST request types as bodies instead of arbitrary domain objects.
- Ensure body getters are side-effect free and classes are free of cycles.
- Pre-test custom body types by serializing them with the shared mapper.
When it happens
Trigger: Calling HTTPRequest.post(...).withBody(obj) where obj is not JSON-serializable — e.g. an object with self-references (infinite recursion), a type Jackson has no serializer for, or a POJO with failing getters that throw during serialization.
Common situations: Passing raw domain objects instead of Iceberg REST request types (like RegisterTableRequest); non-serializable custom types (InputStream, lambdas) in the body; getters that throw IllegalStateException during property access.
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
- Unrecognized update requirement. Cannot convert to json: %s
- UncheckedIOException wrapping IOException from JSON generati
- Unsupported task type:
- Cannot write unknown type:
- Failed to write json for: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/1bb8690d3896aef8.
Report an issue: GitHub.