opendataloader-project/opendataloader-pdf · error · IOException

Invalid upload response: missing fileId in data

Error message

Invalid upload response: missing fileId in data

What it means

The upload response JSON contains a 'data' object but it lacks a 'fileId' field, or 'fileId' exists but is not a textual JSON node (e.g., it's a number or object). The fileId is critical — it is the handle used in all subsequent API calls (getVisualInfo, deleteFile). Without it, the conversion pipeline cannot proceed.

Source

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

                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();
        }
    }

    /**
     * Retrieves visual info for an uploaded file.
     *
     * @param fileId The file ID from upload.
     * @return The visual info JSON response.
     * @throws IOException If the request fails.
     */
    private JsonNode getVisualInfo(String fileId) throws IOException {
        String url = baseUrl + String.format(VISUALINFO_ENDPOINT, fileId) +
            "?engine=" + ENGINE +
            "&dlaMode=" + DLA_MODE +
            "&ocrMode=" + OCR_MODE;

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Log root.toString() or dataNode.toString() to inspect the actual field names in the data object.
  2. If the field is named differently (e.g., 'id'), update the client to check multiple possible key names or upgrade the library to match the server version.
  3. Verify that the server is the expected version — compare the response schema against the Hancom API documentation.
  4. If using a mock server for testing, ensure it returns {"data":{"fileId":"test-file-id"}}.

Example fix

// before: only checks 'fileId', strict textual check
JsonNode fileIdNode = dataNode.get("fileId");
if (fileIdNode == null || !fileIdNode.isTextual()) {
    throw new IOException("Invalid upload response: missing fileId in data");
}

// after: also log the data object for diagnosis
JsonNode fileIdNode = dataNode.get("fileId");
if (fileIdNode == null || !fileIdNode.isTextual()) {
    throw new IOException("Invalid upload response: missing fileId in data. "
        + "Data object: " + dataNode);
}
Defensive patterns

Strategy: validation

Validate before calling

// Cannot pre-validate from the client side.
// During development, test against the real server and log the data object:
// This is a server-side contract issue, not a client-side validation opportunity.

Try / catch

try {
    fileId = client.uploadFile(pdfBytes);
} catch (IOException e) {
    if (e.getMessage().contains("missing fileId")) {
        LOGGER.severe("Upload response missing fileId. Check API version compatibility.");
        // Do not retry — same response will come back
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling HancomClient.uploadFile(pdfBytes) when the server's 'data' object is present but structurally incomplete — fileId might be null, missing, or returned under a different key name (e.g., 'id', 'file_id', 'uid'). Also triggered if the server returns a numeric fileId that Jackson sees as non-textual via isTextual() check.

Common situations: API version mismatch where 'fileId' was renamed to 'id' or 'file_id'; server-side bug where the upload succeeded but the response serializer skipped the fileId field; testing against a mock server that populates 'data' with placeholder values; partial response due to serialization timeout on the server.

Related errors


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