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

  1. Retry the pages request — a single empty body from a healthy worker is typically transient.
  2. Check the worker logs for a crash between sending headers and writing the body.
  3. Inspect network path (proxies, load balancers, HTTP/2 resets) for payload-dropping intermediaries.
  4. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/557d143bc632231b. Report an issue: GitHub.