prestodb/presto · error · ProxyException

Bad Content-Type from remote Presto server:${contentType}

Error message

Bad Content-Type from remote Presto server:${contentType}

What it means

After confirming a Content-Type exists, the proxy requires it to be application/json. Any other media type (text/html, text/plain, etc.) triggers this ProxyException with the offending type appended. It means the 200 response body is not the JSON the proxy expects.

Source

Thrown at presto-proxy/src/main/java/com/facebook/presto/proxy/ProxyResponseHandler.java:61

    }

    @Override
    public ProxyResponse handle(Request request, Response response)
    {
        if (response.getStatusCode() == NO_CONTENT.code()) {
            return new ProxyResponse(response.getHeaders(), new byte[0]);
        }

        if (response.getStatusCode() != OK.code()) {
            throw new ProxyException(format("Bad status code from remote Presto server: %s: %s", response.getStatusCode(), readBody(response)));
        }

        String contentType = response.getHeader(CONTENT_TYPE);
        if (contentType == null) {
            throw new ProxyException("No Content-Type set in response from remote Presto server");
        }
        if (!MediaType.parse(contentType).is(MEDIA_TYPE_JSON)) {
            throw new ProxyException("Bad Content-Type from remote Presto server:" + contentType);
        }

        try {
            return new ProxyResponse(response.getHeaders(), toByteArray(response.getInputStream()));
        }
        catch (IOException e) {
            throw new ProxyException("Failed reading response from remote Presto server", e);
        }
    }

    private static String readBody(Response response)
    {
        try {
            return new String(toByteArray(response.getInputStream()), US_ASCII);
        }
        catch (IOException e) {
            return "";
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Check the reported Content-Type in the message to identify what answered.
  2. Curl the remote endpoint directly and inspect the body (likely HTML from an auth page or LB).
  3. Bypass/fix the intercepting layer or supply credentials so the real JSON API answers.
  4. Confirm the remote server URI points at the Presto coordinator API.
Defensive patterns

Strategy: validation

Validate before calling

// assert the remote endpoint speaks JSON before proxying
const probe = await fetch(backendUri + path, { headers });
const ct = (probe.headers.get("content-type") || "");
if (!ct.startsWith("application/json")) throw new Error("Non-JSON backend response: " + ct + " — check for SSO/LB interception");

Try / catch

try {
  return await proxyCall(req);
} catch (e) {
  if (String(e.message).startsWith("Bad Content-Type")) {
    // likely an HTML auth page; re-authenticate or fix routing
  } else throw e;
}

Prevention

When it happens

Trigger: Remote server returned 200 with a non-JSON Content-Type, e.g. an HTML login/error page from an auth gateway, or text/plain from a misconfigured endpoint.

Common situations: Reverse proxy or SSO layer intercepting requests and returning an HTML page with 200; hitting the wrong backend path; Presto version/endpoint mismatch.

Related errors


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