opendataloader-project/opendataloader-pdf · error · IOException

Hancom AI server is not available at %s Check that the serve

Error message

Hancom AI server is not available at %s
Check that the server is running and accessible.

What it means

The outer health-check failure for the Hancom AI backend: the catch at line 180 wraps any IOException from the /ping call (both connection failures and the non-2xx case from error 50) into a single 'not available' message with the original as cause. It means the client could not confirm the backend is healthy and will not proceed with the Hancom pipeline.

Source

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

    @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
        // since nothing shared is mutated).
        CropOutput cropOutput = request.getCropOutput();

        try (PageImageCache pageImageCache = createPageImageCache()) {

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Start the Hancom AI server and confirm it is listening on the configured port (default 18008)
  2. Set the correct address via --hybrid-url http://host:port
  3. Verify with curl http://host:18008/ping that it returns 2xx
  4. Inspect getCause() to distinguish connection-refused from a non-2xx /ping
  5. Use --hybrid-fallback or run without --hybrid for Java-only output

Example fix

// before
opendataloader-pdf --hybrid=hancom-ai in.pdf
// after
opendataloader-pdf --hybrid=hancom-ai --hybrid-fallback in.pdf
Defensive patterns

Strategy: fallback

Validate before calling

// Probe the Hancom AI server before running
try (java.net.Socket s = new java.net.Socket()) {
    s.connect(new InetSocketAddress(host, 18008), 1000);
} catch (IOException e) {
    config.setHybrid(null); // Java-only
}

Try / catch

try {
    client.checkAvailability();
} catch (IOException e) {
    Throwable cause = e.getCause(); // distinguishes conn-refused vs non-2xx /ping
    log.warn("Hancom AI unavailable: {}", e.getMessage());
    config.getHybridConfig().setFallbackToJava(true);
}

Prevention

When it happens

Trigger: healthClient.newCall(request).execute() throws IOException (connection refused/timeout/DNS) OR the inner throw at line 177 (non-2xx /ping) propagates into this catch.

Common situations: Hancom AI server not started; wrong host/port (default 18008); firewall/network isolation; server crashed or still booting; /ping returning non-2xx on this server build.

Related errors


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