opendataloader-project/opendataloader-pdf · error · IOException

Empty response body from upload

Error message

Empty response body from upload

What it means

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.

Source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomClient.java:198

            .addFormDataPart("file", DEFAULT_FILENAME,
                RequestBody.create(pdfBytes, MEDIA_TYPE_PDF))
            .build();

        Request request = new Request.Builder()
            .url(baseUrl + UPLOAD_ENDPOINT)
            .post(requestBody)
            .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                ResponseBody body = response.body();
                String bodyStr = body != null ? body.string() : "";
                throw new IOException("Hancom upload failed with status " + response.code() + ": " + bodyStr);
            }

            ResponseBody body = response.body();
            if (body == null) {
                throw new IOException("Empty response body from upload");
            }

            JsonNode root = objectMapper.readTree(body.string());
            // Response format: {"codeNum":0,"code":"file.upload.success","data":{"fileId":"...",...}}
            JsonNode dataNode = root.get("data");
            if (dataNode == null) {
                throw new IOException("Invalid upload response: missing data field");
            }
            JsonNode fileIdNode = dataNode.get("fileId");
            if (fileIdNode == null || !fileIdNode.isTextual()) {
                throw new IOException("Invalid upload response: missing fileId in data");
            }

            return fileIdNode.asText();
        }
    }

    /**

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Retry the upload — this is almost always a transient transport-level issue.
  2. Check for proxy/load balancer configurations that might strip or buffer response bodies (look for proxy_buffering, response size limits).
  3. Test the upload directly bypassing any proxy to isolate where the body is lost.
  4. Contact Hancom support if persistent — a 2xx with no body is a server-side contract violation.
  5. Add request-level logging (OkHttp interceptor) to capture the full response headers and confirm Content-Length.

Example fix

// No client-side fix possible — this is a server/proxy anomaly.
// Best practice: retry and log the response headers for diagnosis.
Response response = httpClient.newCall(request).execute();
if (response.isSuccessful() && response.body() == null) {
    LOGGER.severe("Upload succeeded (HTTP " + response.code() + ") but body is null. Headers: "
        + response.headers());
    throw new IOException("Empty response body from upload");
}
Defensive patterns

Strategy: retry

Validate before calling

// Cannot pre-validate server response body existence.
// Ensure the OkHttp client has response body logging enabled for diagnosis.
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new HttpLoggingInterceptor().setLevel(Level.HEADERS))
    .build();

Try / catch

try {
    fileId = client.uploadFile(pdfBytes);
} catch (IOException e) {
    if (e.getMessage().contains("Empty response body")) {
        // Transient transport anomaly — retry once
        fileId = client.uploadFile(pdfBytes);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of opendataloader-project/opendataloader-pdf@a7789b8e77 (2026-08-14). Data as JSON: /api/errors/1723e27f788b512a. Report an issue: GitHub.