opendataloader-project/opendataloader-pdf · error · IOException

Hancom AI server at %s returned HTTP %s

Error message

Hancom AI server at %s returned HTTP %s

What it means

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.

Source

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

            return null;
        }
    }

    @Override
    public void checkAvailability() throws IOException {
        OkHttpClient healthClient = httpClient.newBuilder()
            .connectTimeout(HEALTH_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)
            .readTimeout(HEALTH_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)
            .build();

        Request request = new Request.Builder()
            .url(baseUrl + PING_ENDPOINT)
            .get()
            .build();

        try (Response response = healthClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Hancom AI server at " + baseUrl +
                    " returned HTTP " + response.code());
            }
        } catch (IOException e) {
            throw new IOException(
                "Hancom AI server is not available at " + baseUrl + "\n"
                + "Check that the server is running and accessible.", e);
        }
    }

    @Override
    public HybridResponse convert(HybridRequest request) throws IOException {
        byte[] pdfBytes = request.getPdfBytes();
        this.sourcePdfShaShort = sha256ShortHex(pdfBytes);
        LOGGER.log(Level.INFO, "Hancom AI: processing PDF ({0} bytes)", pdfBytes.length);

        // Crop / page-image destination travels with the request, not the
        // cached client's config, so the per-document target is correct even
        // when the client is reused across documents (and is concurrency-safe

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Wait for the server to finish warm-up and retry checkAvailability()
  2. Confirm the server exposes /ping (vs only /health) at this version
  3. Check server logs for the non-2xx cause
  4. Use --hybrid-fallback to proceed Java-only
Defensive patterns

Strategy: retry

Try / catch

// Error 50 is internally re-wrapped into error 51, so handle at the
// checkAvailability() level (see error 51 strategy).

Prevention

When it happens

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

Common situations: Server still initializing (503); wrong endpoint path on a versioned server; auth required on /ping returning 401/403; server in a degraded state.

Related errors


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