prestodb/presto · error · PageTransportErrorException
Response body is null
Error message
Response body is null
What it means
After all response headers (task instance id, token, complete) validate, the client reads the page payload from the OkHttp response body. OkHttp can legally return a null body, so the client guards it explicitly and throws PageTransportErrorException instead of NPE, because a null body means the server sent no pages data despite the correct content type.
Source
Thrown at presto-spark-base/src/main/java/com/facebook/presto/spark/execution/http/PrestoSparkHttpTaskClient.java:780
if (contentType == null) {
throw new PageTransportErrorException(
HostAddress.fromUri(request.url().uri()),
format("%s header is not set: %s", CONTENT_TYPE, response));
}
if (!mediaTypeMatches(contentType, PRESTO_PAGES_TYPE)) {
throw new PageTransportErrorException(
HostAddress.fromUri(request.url().uri()),
format("Expected %s response from server but got %s", PRESTO_PAGES_TYPE, contentType));
}
String taskInstanceId = getTaskInstanceId(request, response);
long token = getToken(request, response);
long nextToken = getNextToken(request, response);
boolean complete = getComplete(request, response);
ResponseBody responseBody = response.body();
if (responseBody == null) {
throw new PageTransportErrorException(
HostAddress.fromUri(request.url().uri()),
"Response body is null");
}
SliceInput input = new InputStreamSliceInput(responseBody.byteStream());
List<SerializedPage> pages = ImmutableList.copyOf(readSerializedPages(input));
PagesResponse pagesResponse = createPagesResponse(taskInstanceId, token, nextToken, pages, complete);
return new PagesBaseResponse(response.code(), convertHeaders(response), pagesResponse);
}
catch (PageTransportErrorException e) {
throw new PageTransportErrorException(
e.getRemoteHost(),
"Error fetching " + request.url(),
e);
}
}
private static ListMultimap<OkHttpHeaderName, String> convertHeaders(Response response)View on GitHub (pinned to 55bb57d202)
Solutions
- Retry the pages request — a single empty body from a healthy worker is typically transient.
- Check the worker logs for a crash between sending headers and writing the body.
- Inspect network path (proxies, load balancers, HTTP/2 resets) for payload-dropping intermediaries.
- Confirm the worker was not concurrently shut down or replaced (task instance gone) during the fetch.
Defensive patterns
Strategy: retry
Validate before calling
// cheap pre-check: ensure endpoint responds and looks like a worker
curl -sS -o /dev/null -w '%{http_code} %{content_type}' http://worker:port/rest/path Try / catch
try {
client.getPagesRequest(location, token, ...);
} catch (PageTransportErrorException e) {
// wrap: bounded retry with backoff, then fail the exchange
retryWithBackoff(() -> client.getPagesRequest(location, token, ...), 3);
} Prevention
- Retry page fetches a bounded number of times before failing the exchange.
- Monitor worker stability; frequent empty bodies indicate crashing workers.
- Keep HTTP clients on HTTP/1.1 or test HTTP/2 resets on your network path.
- Alert on proxies that alter or drop payloads.
When it happens
Trigger: Server returns a response (correct content type and headers) with an empty or body-less message — e.g. a 204-style response or a truncated/empty transfer from the worker.
Common situations: Worker crashed mid-response leaving an empty body; HTTP/2 stream reset producing a bodyless response; intermediary (proxy/gateway) dropping the payload while preserving headers.
Related errors
- Expected response code to be 200, but was %s:%n%s
- %s header is not set: %s
- Error fetching
- shuffleWriteInfo and broadcastBasePath can not be specified
- Error reading response from server
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/557d143bc632231b.
Report an issue: GitHub.