{"record":{"id":"d541dd6b484d533a","repo":"prestodb/presto","slug":"nativeplanchecker-unknown-conversion-failure","errorCode":"NATIVEPLANCHECKER_UNKNOWN_CONVERSION_FAILURE","errorMessage":"Error response without failure from native plan checker with code: {statusCode}","messagePattern":"Error response without failure from native plan checker with code: (.+?)","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/nativechecker/NativePlanChecker.java","lineNumber":231,"sourceCode":"                .setHeader(CONTENT_TYPE, JSON_UTF_8.toString())\n                .setBodyGenerator(createStaticBodyGenerator(requestBodyJson, UTF_8))\n                .build();\n    }\n\n    private URI getSidecarLocation()\n    {\n        Node sidecarNode = nodeManager.getSidecarNode();\n        return HttpUriBuilder\n                .uriBuilderFrom(sidecarNode.getHttpUri())\n                .appendPath(PLAN_CONVERSION_ENDPOINT)\n                .build();\n    }\n\n    private NativeSidecarFailureInfo processResponseFailure(StringResponse response)\n    {\n        String responseBody = response.getBody();\n        if (responseBody == null || responseBody.isEmpty()) {\n            throw new PrestoException(NATIVEPLANCHECKER_UNKNOWN_CONVERSION_FAILURE, \"Error response without failure from native plan checker with code: \" + response.getStatusCode());\n        }\n\n        PlanConversionResponse planConversionResponse = PLAN_CONVERSION_RESPONSE_JSON_CODEC.fromJson(responseBody);\n        if (planConversionResponse.getFailures().isEmpty()) {\n            throw new PrestoException(NATIVEPLANCHECKER_UNKNOWN_CONVERSION_FAILURE, \"Error response without failure from native plan checker with code: \" + response.getStatusCode());\n        }\n\n        return planConversionResponse.getFailures().get(0);\n    }\n\n    private static class CheckInternalVisitor\n            extends PlanVisitor<Boolean, Void>\n    {\n        @Override\n        public Boolean visitTableScan(TableScanNode tableScan, Void context)\n        {\n            TableHandle handle = tableScan.getTable();\n            return ConnectorId.isInternalSystemConnector(handle.getConnectorId());","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-native-sidecar-plugin/src/main/java/com/facebook/presto/sidecar/nativechecker/NativePlanChecker.java#L213-L249","documentation":"When the plan checker returns a non-200 response, NativePlanChecker.processResponseFailure expects the body to decode into a PlanConversionResponse containing failure info. If the body is null or empty, there is nothing to convert, so it throws NATIVEPLANCHECKER_UNKNOWN_CONVERSION_FAILURE with the HTTP status code — the real failure reason is unknown.","triggerScenarios":"validateFragment -> runValidation gets a non-200 response whose body is null or empty; processResponseFailure hits the first guard.","commonSituations":"Sidecar crashing mid-request (empty 500 body); proxy/load balancer intercepting and returning bare status codes (502/504 with empty body); request timeout at the gateway.","solutions":["Check the HTTP status code in the message and the sidecar/proxy logs for that request.","If a proxy returns empty 502/504, fix connectivity/timeouts between coordinator and sidecar.","Check sidecar container logs for a crash (OOM) during plan conversion.","Retry the query once sidecar is healthy; ensure sidecar returns structured failure JSON on errors."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// require structured errors from the checker service\nassertSidecarReturnsJsonErrors(); // verify sidecar never returns bare/empty error bodies","typeGuard":"boolean hasFailureBody(StringResponse r) { return r.getBody() != null && !r.getBody().isEmpty(); }","tryCatchPattern":"try { validateFragment(fragment); }\ncatch (PrestoException e) {\n    if (\"NATIVEPLANCHECKER_UNKNOWN_CONVERSION_FAILURE\".equals(e.getErrorCode().getName())) {\n        log.warn(\"Empty checker error body; checking sidecar/proxy health then retrying\");\n        if (sidecarHealthy()) retryOnce(); else failFast(e);\n    } else throw e;\n}","preventionTips":["Bypass or correctly configure proxies between coordinator and sidecar","Ensure sidecar serializes failure JSON for all error paths","Monitor for sidecar OOM/crash loops","Check the status code in the message to distinguish 5xx vs gateway errors"],"tags":["sidecar","http-response","plan-validation","native-engine"],"backgroundTag":"empty-error-response","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"}