{"record":{"id":"15a51d87cdd38945","repo":"opendataloader-project/opendataloader-pdf","slug":"pdf2img-page-png-data-is-not-valid-base64","errorCode":null,"errorMessage":"pdf2img PAGE_PNG_DATA is not valid Base64","messagePattern":"pdf2img PAGE_PNG_DATA is not valid Base64","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomAIClient.java","lineNumber":722,"sourceCode":"            JsonNode innerResult = pageResult.get(\"RESULT\");\n            if (innerResult == null) {\n                throw new IOException(\"pdf2img inner RESULT is null\");\n            }\n\n            String pngBase64 = innerResult.has(\"PAGE_PNG_DATA\")\n                ? innerResult.get(\"PAGE_PNG_DATA\").asText() : null;\n            if (pngBase64 == null || pngBase64.isEmpty()) {\n                throw new IOException(\"pdf2img PAGE_PNG_DATA is empty\");\n            }\n\n            byte[] pngBytes;\n            try {\n                pngBytes = Base64.getDecoder().decode(pngBase64);\n            } catch (IllegalArgumentException e) {\n                // fetchPageImage is declared to throw IOException and callers catch\n                // only IOException. Escaping IAE would abort the whole conversion\n                // instead of skipping the failed page.\n                throw new IOException(\"pdf2img PAGE_PNG_DATA is not valid Base64\", e);\n            }\n            BufferedImage image = ImageIO.read(new ByteArrayInputStream(pngBytes));\n            if (image == null) {\n                throw new IOException(\"pdf2img PAGE_PNG_DATA is not a readable image\");\n            }\n            if (cropOutput.active()) {\n                savePageImageFile(cropOutput.directory(), pageIndex, pngBytes);\n            }\n            return image;\n        }\n    }\n\n    /**\n     * Sends a cropped image to IMAGE_CAPTIONING and returns the caption text.\n     */\n    /** Image-captioning result: caption text + the model's self-reported confidence. */\n    static final class CaptionResult {\n        final String caption;","sourceCodeStart":704,"sourceCodeEnd":740,"githubUrl":"https://github.com/opendataloader-project/opendataloader-pdf/blob/a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8/java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomAIClient.java#L704-L740","documentation":"PAGE_PNG_DATA was present and non-empty but failed Base64 decoding (IllegalArgumentException). fetchPageImage wraps the IAE as IOException with a clear message, because the method signature only declares IOException and an escaping IAE would abort the entire conversion instead of just skipping the page. Indicates the payload is not valid Base64 (truncated, corrupted, or wrong encoding).","triggerScenarios":"Base64.getDecoder().decode(pngBase64) throws IllegalArgumentException on the PAGE_PNG_DATA string inside fetchPageImage; the catch re-throws it as IOException.","commonSituations":"Truncated response body from a proxy cutting large images; backend returning URL-safe Base64 while the client uses standard decoder; corrupted transfer; backend bug emitting raw bytes or a data-URI prefix.","solutions":["Check whether the backend emits standard vs URL-safe Base64 and decode accordingly","Strip any 'data:image/png;base64,' prefix if the backend adds one","Bypass proxies that may truncate large base64 payloads","Retry the page; transient truncation often clears","Log the first/last chars of pngBase64 to diagnose format"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return cache.getOrFetch(pageNum, idx -> client.fetchPageImage(pdf, idx, crop));\n} catch (IOException e) {\n    String m = e.getMessage();\n    if (m.contains(\"not valid Base64\")) {\n        // possible URL-safe Base64 or data-URI prefix; retry with a tolerant decoder\n        log.warn(\"page {} base64 decode failed — check backend encoding\", pageNum);\n    }\n    continue;\n}","preventionTips":["Confirm the backend emits standard (MIME) Base64, not URL-safe or a data-URI prefix","Bypass proxies that may truncate large base64 payloads","Retry once — transient truncation often clears on the next request"],"tags":["hybrid","hancom-ai","pdf2img","base64","response-parsing"],"backgroundTag":null,"analyzedSha":"a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8","analyzedAt":"2026-08-14T05:22:03.953Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}