{"record":{"id":"5f99ef3895589541","repo":"opendataloader-project/opendataloader-pdf","slug":"hancom-ai-server-at-s-returned-http-s","errorCode":null,"errorMessage":"Hancom AI server at %s returned HTTP %s","messagePattern":"Hancom AI server at (.+?) returned HTTP (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomAIClient.java","lineNumber":177,"sourceCode":"            return null;\n        }\n    }\n\n    @Override\n    public void checkAvailability() throws IOException {\n        OkHttpClient healthClient = httpClient.newBuilder()\n            .connectTimeout(HEALTH_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)\n            .readTimeout(HEALTH_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)\n            .build();\n\n        Request request = new Request.Builder()\n            .url(baseUrl + PING_ENDPOINT)\n            .get()\n            .build();\n\n        try (Response response = healthClient.newCall(request).execute()) {\n            if (!response.isSuccessful()) {\n                throw new IOException(\"Hancom AI server at \" + baseUrl +\n                    \" returned HTTP \" + response.code());\n            }\n        } catch (IOException e) {\n            throw new IOException(\n                \"Hancom AI server is not available at \" + baseUrl + \"\\n\"\n                + \"Check that the server is running and accessible.\", e);\n        }\n    }\n\n    @Override\n    public HybridResponse convert(HybridRequest request) throws IOException {\n        byte[] pdfBytes = request.getPdfBytes();\n        this.sourcePdfShaShort = sha256ShortHex(pdfBytes);\n        LOGGER.log(Level.INFO, \"Hancom AI: processing PDF ({0} bytes)\", pdfBytes.length);\n\n        // Crop / page-image destination travels with the request, not the\n        // cached client's config, so the per-document target is correct even\n        // when the client is reused across documents (and is concurrency-safe","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/opendataloader-project/opendataloader-pdf/blob/a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8/java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomAIClient.java#L159-L195","documentation":"The Hancom AI health check (GET /ping) connected and received an HTTP response, but the status was not 2xx. This is thrown first inside the try block; note the surrounding catch immediately re-wraps it into the 'not available' message (error 51), so end users typically observe error 51. The distinct message documents that the server was reachable but rejected /ping.","triggerScenarios":"GET to baseUrl + '/ping' returns a non-2xx status inside the try-with-resources; the IOException thrown at line 177 is caught at line 180 and re-wrapped.","commonSituations":"Server still initializing (503); wrong endpoint path on a versioned server; auth required on /ping returning 401/403; server in a degraded state.","solutions":["Wait for the server to finish warm-up and retry checkAvailability()","Confirm the server exposes /ping (vs only /health) at this version","Check server logs for the non-2xx cause","Use --hybrid-fallback to proceed Java-only"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Error 50 is internally re-wrapped into error 51, so handle at the\n// checkAvailability() level (see error 51 strategy).","preventionTips":["Ensure /ping returns 2xx once the server is ready","Add a readiness wait loop after server start","Confirm the server build exposes /ping (not only /health)"],"tags":["network","hybrid","hancom-ai","health-check","http-status"],"backgroundTag":null,"analyzedSha":"a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8","analyzedAt":"2026-08-14T05:22:03.953Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}