opendataloader-project/opendataloader-pdf · critical · IOException

Hybrid server is not available at

Error message

Hybrid server is not available at %s
Please check the server URL and ensure the Hancom API is accessible.
Or pass --hybrid-fallback to fall back to Java-only output for this run.
Or run without --hybrid flag for Java-only processing.

What it means

HancomClient.checkAvailability() sends a HEAD request to the base URL and any IOException (connection refused, DNS resolution failure, connect timeout, SSL handshake error) is caught and re-thrown with actionable guidance. A successful HTTP response of any status code (including 401/403) proves connectivity because the Hancom API requires authentication on all endpoints. This error means the server is entirely unreachable, not merely returning an error code.

Solutions

  1. Verify the server URL with curl: `curl -I <url>` or `curl -sS -o /dev/null -w '%{http_code}' <url>` — any HTTP status code (even 401) confirms reachability.
  2. Pass --hybrid-fallback to continue processing with Java-only output for this run while the server issue is investigated.
  3. Drop the --hybrid flag entirely to run in pure Java mode without any availability check.
  4. Check DNS resolution: `nslookup <hostname>` or `dig <hostname>` to rule out DNS failures.
  5. If using a self-hosted Hancom instance, confirm the service is running and the port is open: `telnet <host> <port>` or `nc -zv <host> <port>`.
  6. For HTTPS endpoints, verify certificate validity with `openssl s_client -connect <host>:443`.

Example fix

// before: throws and aborts the whole run
client.checkAvailability();

// after: graceful fallback to Java-only processing
try {
    client.checkAvailability();
} catch (IOException e) {
    if (config.isFallbackToJava()) {
        LOGGER.warning("Hybrid server unavailable, falling back to Java-only: " + e.getMessage());
        // proceed with Java-only pipeline
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: fallback

Validate before calling

// Validate reachability before starting hybrid processing
try {
    client.checkAvailability();
} catch (IOException e) {
    if (config.isFallbackToJava()) {
        LOGGER.warning("Hybrid unavailable, using Java-only mode");
        runJavaOnlyPipeline();
        return;
    }
    throw e;
}

Try / catch

try {
    client.checkAvailability();
} catch (IOException e) {
    // The error message already suggests --hybrid-fallback and removing --hybrid
    if (config.isFallbackToJava()) {
        proceedWithJavaOnly();
    } else {
        // Re-throw — the user must decide whether to fall back
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling HybridClient.checkAvailability() on a HancomClient when the server URL is wrong, the host is down, a firewall blocks the port, DNS cannot resolve the hostname, or the HEALTH_CHECK_TIMEOUT_MS window expires before the TCP connection establishes. Also triggered when an HTTPS URL is used but the server certificate is invalid or the TLS version is unsupported.

Common situations: Wrong --hybrid-url (typo, missing port, forgot /api path suffix); server not started yet; corporate VPN or firewall blocking outbound access to dataloader.cloud.hancom.com; using http:// against an HTTPS-only endpoint; DNS outage or stale cached entry pointing to a decommissioned IP.

Related errors


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

Appendix: source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HancomClient.java:121

    @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)
            .head()
            .build();

        try (Response response = healthClient.newCall(request).execute()) {
            // Any HTTP response (including 4xx/5xx) means the server is reachable.
            // Hancom API requires authentication for all endpoints, so a 401/403
            // is expected and still proves connectivity.
        } catch (IOException e) {
            throw new IOException(
                "Hybrid server is not available at " + baseUrl + "\n"
                + "Please check the server URL and ensure the Hancom API is accessible.\n"
                + "Or pass --hybrid-fallback to fall back to Java-only output for this run.\n"
                + "Or run without --hybrid flag for Java-only processing.", e);
        }
    }

    @Override
    public HybridResponse convert(HybridRequest request) throws IOException {
        String fileId = null;
        try {
            // Step 1: Upload PDF
            fileId = uploadFile(request.getPdfBytes());
            LOGGER.log(Level.FINE, "Uploaded file with ID: {0}", fileId);

            // Step 2: Get visual info
            JsonNode visualInfo = getVisualInfo(fileId);
            LOGGER.log(Level.FINE, "Retrieved visual info for file: {0}", fileId);

View on GitHub (pinned to a7789b8e77)