{"record":{"id":"99690621ad844f28","repo":"prestodb/presto","slug":"expected-s-response-from-server-but-got-s-996906","errorCode":null,"errorMessage":"Expected %s response from server but got %s","messagePattern":"Expected (.+?) response from server but got (.+?)","errorType":"exception","errorClass":"PageTransportErrorException","httpStatus":null,"severity":"error","filePath":"presto-spark-base/src/main/java/com/facebook/presto/spark/execution/http/PrestoSparkHttpTaskClient.java","lineNumber":768,"sourceCode":"                    catch (RuntimeException | IOException e) {\n                        // Ignored. Just return whatever message we were able to decode\n                    }\n                    throw new PageTransportErrorException(\n                            HostAddress.fromUri(request.url().uri()),\n                            format(\"Expected response code to be 200, but was %s:%n%s\",\n                                    response.code(),\n                                    body.toString()));\n                }\n\n                // invalid content type can happen when an error page is returned, but is unlikely given the above 200\n                String contentType = response.header(CONTENT_TYPE);\n                if (contentType == null) {\n                    throw new PageTransportErrorException(\n                            HostAddress.fromUri(request.url().uri()),\n                            format(\"%s header is not set: %s\", CONTENT_TYPE, response));\n                }\n                if (!mediaTypeMatches(contentType, PRESTO_PAGES_TYPE)) {\n                    throw new PageTransportErrorException(\n                            HostAddress.fromUri(request.url().uri()),\n                            format(\"Expected %s response from server but got %s\", PRESTO_PAGES_TYPE, contentType));\n                }\n\n                String taskInstanceId = getTaskInstanceId(request, response);\n                long token = getToken(request, response);\n                long nextToken = getNextToken(request, response);\n                boolean complete = getComplete(request, response);\n\n                ResponseBody responseBody = response.body();\n                if (responseBody == null) {\n                    throw new PageTransportErrorException(\n                            HostAddress.fromUri(request.url().uri()),\n                            \"Response body is null\");\n                }\n\n                SliceInput input = new InputStreamSliceInput(responseBody.byteStream());\n                List<SerializedPage> pages = ImmutableList.copyOf(readSerializedPages(input));","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-spark-base/src/main/java/com/facebook/presto/spark/execution/http/PrestoSparkHttpTaskClient.java#L750-L786","documentation":"PrestoSparkHttpTaskClient validates every HTTP response it downloads pages from: the response must declare Content-Type application/vnd.presto.pages (PRESTO_PAGES_TYPE). If the header is absent or a different media type is returned (e.g. an HTML error page or JSON error), it wraps it in a PageTransportErrorException so the caller treats the endpoint as speaking the wrong protocol rather than returning bad data.","triggerScenarios":"Calling the pages-acquire endpoint (getPagesRequest) and the server replies 200 OK but with a Content-Type other than application/vnd.presto.pages — e.g. an error page from a proxy, a JSON-encoded failure from the native worker, or a custom serializer writing the wrong MIME type.","commonSituations":"A reverse proxy or load balancer intercepts the request and returns an HTML 4xx/5xx page with text/html; a Presto version mismatch where the Spark-side worker returns pages encoded as JSON instead of the Presto pages media type; a misconfigured native worker binary that does not use Smile/pages serialization.","solutions":["Check what the remote actually returned: log/inspect the %s value in the message to see the unexpected content type.","Verify the target server is a genuine Presto native worker on the expected port, not a proxy or another service.","Ensure client and server Presto versions match (same pages serialization protocol).","If a proxy is in the path, bypass it or configure it to pass the response through unchanged (no content-type rewriting, no HTML error interstitials).","Retry the request; transient worker failures can momentarily return error bodies instead of pages."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before reading pages, check the declared content type\nString contentType = response.header(\"Content-Type\");\nif (contentType == null || !contentType.contains(\"application/vnd.presto.pages\")) {\n    throw new IllegalStateException(\"Non-pages response from \" + request.url() + \": \" + contentType);\n}","typeGuard":"// narrowing guard for a valid pages response\nboolean isPagesResponse(Response r) {\n    String ct = r.header(\"Content-Type\");\n    return ct != null && ct.trim().startsWith(\"application/vnd.presto.pages\");\n}","tryCatchPattern":"try {\n    PagesBaseResponse resp = client.getPagesRequest(...);\n} catch (PageTransportErrorException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Expected\")) {\n        // wrong content type: re-discover a healthy worker and retry\n    }\n}","preventionTips":["Keep proxies/service mesh from rewriting or inspecting worker response bodies.","Pin client and worker to matching Presto versions.","Health-check the worker port before issuing pages requests.","Retry transient failures before failing the task."],"tags":["http","content-type","spark","native-worker"],"backgroundTag":"unexpected-content-type","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}