opendataloader-project/opendataloader-pdf · error · IOException

pdf2img returned HTTP %s

Error message

pdf2img returned HTTP %s

What it means

fetchPageImage posts the PDF page to the /support/pdf2img endpoint; a non-2xx status is converted to IOException. This is a per-page render error: callers (recognizeTableStructures, captionFigures) catch IOException and skip just that page with a WARNING, so it degrades rather than aborts the whole conversion unless it escapes.

Source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomAIClient.java:688

    private BufferedImage fetchPageImage(byte[] pdfBytes, int pageIndex, CropOutput cropOutput)
            throws IOException {
        MultipartBody body = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("REQUEST_ID",
                "odl-" + sourcePdfShaShort + "-pdf2img-p" + pageIndex)
            .addFormDataPart("PAGE_INDEX", String.valueOf(pageIndex))
            .addFormDataPart("FILE", DEFAULT_FILENAME,
                RequestBody.create(pdfBytes, MEDIA_TYPE_PDF))
            .build();

        Request httpRequest = new Request.Builder()
            .url(baseUrl + PDF2IMG_ENDPOINT)
            .post(body)
            .build();

        try (Response response = httpClient.newCall(httpRequest).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("pdf2img returned HTTP " + response.code());
            }

            ResponseBody respBody = response.body();
            if (respBody == null) {
                throw new IOException("pdf2img returned empty body");
            }

            JsonNode root = objectMapper.readTree(respBody.string());
            // Navigate: RESULT[0].RESULT.PAGE_PNG_DATA
            JsonNode resultArr = root.get("RESULT");
            if (resultArr == null || !resultArr.isArray() || resultArr.size() == 0) {
                throw new IOException("pdf2img RESULT is empty");
            }

            JsonNode pageResult = resultArr.get(0);
            JsonNode innerResult = pageResult.get("RESULT");
            if (innerResult == null) {
                throw new IOException("pdf2img inner RESULT is null");

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Check the backend pdf2img service logs for the failing page index
  2. Confirm PAGE_INDEX is 0/1-based as the backend expects
  3. Retry the page (the cache will re-fetch on next getOrFetch after the corrupt entry is cleared)
  4. Accept the degraded result: affected tables/figures are skipped with a WARNING
  5. Restart the backend pdf2img component if it crashed
Defensive patterns

Strategy: try-catch

Validate before calling

// Before relying on page images, sanity-check page range against the PDF
if (pageIndex < 0 || pageIndex >= pageCount) {
    throw new IllegalArgumentException("page index out of range: " + pageIndex);
}

Try / catch

// fetchPageImage is called via the cache; per-page handlers already catch:
try {
    pageImage = cache.getOrFetch(pageNum, idx -> client.fetchPageImage(pdf, idx, crop));
} catch (IOException e) {
    log.warn("skipping page {}: {}", pageNum, e.getMessage());
    continue; // degrade gracefully, skip this page's tables/figures
}

Prevention

When it happens

Trigger: POST to baseUrl + '/support/pdf2img' with PAGE_INDEX and FILE returns a non-2xx HTTP code inside fetchPageImage's try-with-resources.

Common situations: pdf2img microservice down or misconfigured; page index out of range for the backend; backend cannot render a specific malformed page; backend resource limits hit on a large page.

Related errors


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