{"record":{"id":"720f9b912c62e017","repo":"apache/iceberg","slug":"unable-to-parse-error-response","errorCode":null,"errorMessage":"Unable to parse error response","messagePattern":"Unable to parse error response","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java","lineNumber":329,"sourceCode":"      }\n\n      super.accept(error);\n    }\n  }\n\n  /**\n   * Request error handler that handles the common cases that are included with all responses, such\n   * as 400, 500, etc.\n   */\n  private static class DefaultErrorHandler extends ErrorHandler {\n    private static final ErrorHandler INSTANCE = new DefaultErrorHandler();\n\n    @Override\n    public ErrorResponse parseResponse(int code, String json) {\n      try {\n        return ErrorResponseParser.fromJson(json);\n      } catch (Exception x) {\n        LOG.warn(\"Unable to parse error response\", x);\n      }\n      return ErrorResponse.builder().responseCode(code).withMessage(json).build();\n    }\n\n    @Override\n    public void accept(ErrorResponse error) {\n      switch (error.code()) {\n        case 400:\n          if (IllegalArgumentException.class.getSimpleName().equals(error.type())) {\n            throw new IllegalArgumentException(error.message());\n          }\n          throw new BadRequestException(\"Malformed request: %s\", error.message());\n        case 401:\n          throw new NotAuthorizedException(\"Not authorized: %s\", error.message());\n        case 403:\n          throw new ForbiddenException(\"Forbidden: %s\", error.message());\n        case 405:\n        case 406:","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java#L311-L347","documentation":"ErrorHandlers' REST error parser converts an HTTP error body into an ErrorResponse via ErrorResponseParser.fromJson. If the body is not valid REST-catalog error JSON (or any parse exception occurs), this warning is logged and a fallback ErrorResponse containing the raw body as the message and the HTTP code is returned, so the original failure is not lost.","triggerScenarios":"A REST catalog server returns a non-standard error payload (HTML error page, plain text, proxy 502 body, empty/invalid JSON) and the client calls errorHandler.parseResponse(code, json) while handling the failed response.","commonSituations":"Reverse proxies/load balancers returning HTML on 502/504, misconfigured catalog endpoints pointing at a web UI, non-Iceberg servers behind the REST URL, chunked/truncated responses.","solutions":["Check the actual endpoint: verify rest.catalog.io-impl URL points to the REST catalog, not a UI or proxy.","Inspect server/proxy logs for the true error behind the non-JSON body.","Increase client debug logging to see the raw response body included in the fallback ErrorResponse message.","Fix upstream (disable HTML error pages, ensure catalog returns RFC-compliant ErrorResponse JSON)."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { tableScan.planFiles(); } catch (RESTException e) { LOG.error(\"REST error (body may be non-JSON): {}\", e.getMessage(), e); }","preventionTips":["Point the catalog URL at a real REST catalog, not a UI/proxy","Disable HTML error pages on proxies in front of the catalog","Log raw response bodies when diagnosing non-JSON errors"],"tags":["rest","http","json","error-handling"],"backgroundTag":"unexpected-response-shape","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}