apache/iceberg · error · RESTException
Invalid (null) response body for request
Error message
Invalid (null) response body for request (expected %s): method=%s, path=%s, status=%d
What it means
handleResponse expects a JSON body for the given responseType after error handling did not throw. If the response has no entity at all (null entity) while a non-empty-body type like LoadTableResponse was expected, the client throws RESTException. It indicates the server responded successfully (or with a non-error status) but without the promised payload.
Solutions
- Verify with curl that the endpoint actually returns a JSON body for the same request.
- Fix the server/route so it returns the expected response type serialized as JSON.
- Check for redirect/middleware/proxy configurations that may strip response bodies.
- Confirm the client is pointing at the right endpoint (path and method) for the operation.
Example fix
// before: server returns 200 with no body
return Response.ok().build();
// after: always serialize the expected response
return Response.ok(LoadTableResponse.builder()
.withTableMetadata(metadata)
.build()).build(); Defensive patterns
Strategy: try-catch
Try / catch
try {
LoadTableResponse resp = client.post(path, body, LoadTableResponse.class, headers);
} catch (RESTException e) {
if (e.getMessage().contains("null) response body")) {
// server returned success without a payload — inspect endpoint/server implementation
}
throw e;
} Prevention
- Verify server endpoints serialize the declared response type.
- Test endpoints with curl to confirm bodies are present.
- Watch for middleware or redirect layers that drop response bodies.
When it happens
Trigger: The server returns a success status (e.g. 200/201) with no response entity for an endpoint the client expects to deserialize into responseType (like a table or namespace metadata response), and emptyBody() does not consider this response empty.
Common situations: Misbehaving or partially implemented catalog server; wrong endpoint routed (e.g. loadTable hit a route that only acknowledges); server stripped the body on redirect/replay; custom catalog implementation forgot to serialize the response.
Related errors
- Failed to encode request body
- Invalid (NOT_MODIFIED) response for request: method=
- Unrecognized update requirement. Cannot convert to json
- Cannot assume role to sign REST requests because is not…
- Cannot build StorageCredential, some of required attributes…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/5a1bf16d4a057a60.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/HTTPClient.java:369
// 304-NOT_MODIFIED is used for freshness-aware loading and requires an ETag sent to the
// server via IF_NONE_MATCH header in the request. If no ETag was sent, we shouldn't
// receive a 304.
throw new RESTException(
"Invalid (NOT_MODIFIED) response for request: method=%s, path=%s",
request.method(), request.path());
}
return null;
}
if (!isSuccessful(response)) {
// The provided error handler is expected to throw, but a RESTException is thrown if not.
String responseBody = extractResponseBodyAsString(response);
throwFailure(response, responseBody, errorHandler);
}
if (response.getEntity() == null) {
throw new RESTException(
"Invalid (null) response body for request (expected %s): method=%s, path=%s, status=%d",
responseType.getSimpleName(), request.method(), request.path(), response.getCode());
}
ObjectReader reader = objectReaderCache.computeIfAbsent(responseType, mapper::readerFor);
if (parserContext != null && !parserContext.isEmpty()) {
reader = reader.with(parserContext.toInjectableValues());
}
return reader.readValue(response.getEntity().getContent());
}
private <T extends RESTResponse> boolean emptyBody(
ClassicHttpResponse response, Class<T> responseType) {
return response.getCode() == HttpStatus.SC_NO_CONTENT
|| response.getCode() == HttpStatus.SC_NOT_MODIFIED
|| (responseType == null && isSuccessful(response));
}
View on GitHub (pinned to 86d9c8fc54)