{"record":{"id":"1723e27f788b512a","repo":"opendataloader-project/opendataloader-pdf","slug":"empty-response-body-from-upload","errorCode":null,"errorMessage":"Empty response body from upload","messagePattern":"Empty response body from upload","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomClient.java","lineNumber":198,"sourceCode":"            .addFormDataPart(\"file\", DEFAULT_FILENAME,\n                RequestBody.create(pdfBytes, MEDIA_TYPE_PDF))\n            .build();\n\n        Request request = new Request.Builder()\n            .url(baseUrl + UPLOAD_ENDPOINT)\n            .post(requestBody)\n            .build();\n\n        try (Response response = httpClient.newCall(request).execute()) {\n            if (!response.isSuccessful()) {\n                ResponseBody body = response.body();\n                String bodyStr = body != null ? body.string() : \"\";\n                throw new IOException(\"Hancom upload failed with status \" + response.code() + \": \" + bodyStr);\n            }\n\n            ResponseBody body = response.body();\n            if (body == null) {\n                throw new IOException(\"Empty response body from upload\");\n            }\n\n            JsonNode root = objectMapper.readTree(body.string());\n            // Response format: {\"codeNum\":0,\"code\":\"file.upload.success\",\"data\":{\"fileId\":\"...\",...}}\n            JsonNode dataNode = root.get(\"data\");\n            if (dataNode == null) {\n                throw new IOException(\"Invalid upload response: missing data field\");\n            }\n            JsonNode fileIdNode = dataNode.get(\"fileId\");\n            if (fileIdNode == null || !fileIdNode.isTextual()) {\n                throw new IOException(\"Invalid upload response: missing fileId in data\");\n            }\n\n            return fileIdNode.asText();\n        }\n    }\n\n    /**","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/opendataloader-project/opendataloader-pdf/blob/a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8/java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomClient.java#L180-L216","documentation":"The Hancom upload endpoint returned a successful (2xx) HTTP status but response.body() is null. OkHttp returns a null body only in extremely rare cases — typically when the server sends a 200/204 with no entity body, or when the response has already been consumed/closed. This indicates a protocol-level anomaly where the server claims success but provides no content to parse for the fileId.","triggerScenarios":"Calling HancomClient.uploadFile(pdfBytes) when the server returns a 204 No Content, a 200 with Content-Length: 0, or the response stream is prematurely closed at the transport layer. This is distinct from error 63 (non-2xx status) — here the server said 'OK' but sent nothing.","commonSituations":"Misconfigured reverse proxy (nginx/HAProxy) that strips the response body for successful POSTs; server-side bug where the upload handler returns before writing the JSON response; HTTP/2 connection issue causing a premature stream reset after headers; intermediate caching layer returning a cached empty response.","solutions":["Retry the upload — this is almost always a transient transport-level issue.","Check for proxy/load balancer configurations that might strip or buffer response bodies (look for proxy_buffering, response size limits).","Test the upload directly bypassing any proxy to isolate where the body is lost.","Contact Hancom support if persistent — a 2xx with no body is a server-side contract violation.","Add request-level logging (OkHttp interceptor) to capture the full response headers and confirm Content-Length."],"exampleFix":"// No client-side fix possible — this is a server/proxy anomaly.\n// Best practice: retry and log the response headers for diagnosis.\nResponse response = httpClient.newCall(request).execute();\nif (response.isSuccessful() && response.body() == null) {\n    LOGGER.severe(\"Upload succeeded (HTTP \" + response.code() + \") but body is null. Headers: \"\n        + response.headers());\n    throw new IOException(\"Empty response body from upload\");\n}","handlingStrategy":"retry","validationCode":"// Cannot pre-validate server response body existence.\n// Ensure the OkHttp client has response body logging enabled for diagnosis.\nOkHttpClient client = new OkHttpClient.Builder()\n    .addInterceptor(new HttpLoggingInterceptor().setLevel(Level.HEADERS))\n    .build();","typeGuard":null,"tryCatchPattern":"try {\n    fileId = client.uploadFile(pdfBytes);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"Empty response body\")) {\n        // Transient transport anomaly — retry once\n        fileId = client.uploadFile(pdfBytes);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Add OkHttp retryOnConnectionFailure(true) to handle transport-level anomalies.","Log response headers when body is null to diagnose proxy/server issues.","Test uploads bypassing any reverse proxy to isolate the source of body stripping."],"tags":["network","http","hancom","upload","hybrid","protocol-error"],"backgroundTag":null,"analyzedSha":"a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8","analyzedAt":"2026-08-14T05:22:03.953Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}