opendataloader-project/opendataloader-pdf · error · IllegalArgumentException

Hybrid backend type cannot be null or empty

Error message

Hybrid backend type cannot be null or empty

What it means

HybridClientFactory.getOrCreate() requires a non-null, non-empty backend type string. This is a programming-error guard — the backend name selects which HybridClient implementation to instantiate and cache. A null or empty string cannot match any backend constant and is rejected before the cache lookup to avoid a confusing NullPointerException downstream.

Source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HybridClientFactory.java:81

    private HybridClientFactory() {
        // Private constructor to prevent instantiation
    }

    /**
     * Gets or creates a hybrid client for the specified backend.
     *
     * <p>Clients are cached and reused across multiple documents to avoid
     * creating new thread pools for each document. Call {@link #shutdown()}
     * when processing is complete to release resources.
     *
     * @param hybrid The backend type (e.g., "docling", "hancom", "azure", "google").
     * @param config The configuration for the hybrid client.
     * @return A HybridClient instance for the specified backend.
     * @throws IllegalArgumentException If the backend type is unknown or not supported.
     */
    public static HybridClient getOrCreate(String hybrid, HybridConfig config) {
        if (hybrid == null || hybrid.isEmpty()) {
            throw new IllegalArgumentException("Hybrid backend type cannot be null or empty");
        }

        String lowerHybrid = hybrid.toLowerCase();

        return CLIENT_CACHE.computeIfAbsent(lowerHybrid, key -> createClient(key, config));
    }

    /**
     * Creates a new hybrid client instance.
     */
    private static HybridClient createClient(String hybrid, HybridConfig config) {
        if (BACKEND_DOCLING_FAST.equals(hybrid)) {
            return new DoclingFastServerClient(config);
        } else if (BACKEND_HANCOM.equals(hybrid)) {
            return new HancomClient(config);
        } else if (BACKEND_HANCOM_AI.equals(hybrid)) {
            return new HancomAIClient(config);
        } else if (BACKEND_AZURE.equals(hybrid)) {

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Provide a valid backend name: one of 'docling-fast', 'hancom', 'hancom-ai' (see HybridClientFactory constants).
  2. Check the CLI invocation — ensure --hybrid has a value: `--hybrid hancom`, not just `--hybrid`.
  3. If the backend name comes from configuration, validate it is present before calling getOrCreate.
  4. Use HybridClientFactory.getSupportedBackends() to list valid options programmatically.

Example fix

// before: unvalidated external input passed directly
String backend = System.getenv("HYBRID_BACKEND");
HybridClient client = HybridClientFactory.getOrCreate(backend, config);

// after: validate before calling
String backend = System.getenv("HYBRID_BACKEND");
if (backend == null || backend.isBlank()) {
    throw new IllegalArgumentException(
        "HYBRID_BACKEND env var is not set. Valid options: "
        + HybridClientFactory.getSupportedBackends());
}
HybridClient client = HybridClientFactory.getOrCreate(backend, config);
Defensive patterns

Strategy: validation

Validate before calling

String backend = getConfiguredBackend(); // from CLI, env, or config file
if (backend == null || backend.isBlank()) {
    throw new IllegalArgumentException(
        "Hybrid backend type is required. Valid options: "
        + HybridClientFactory.getSupportedBackends());
}
HybridClient client = HybridClientFactory.getOrCreate(backend, config);

Type guard

// Check that the backend string is non-empty before calling the factory
public static boolean isValidBackendName(String backend) {
    return backend != null && !backend.isBlank();
}

Try / catch

try {
    client = HybridClientFactory.getOrCreate(backend, config);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("cannot be null or empty")) {
        // Programming error — fix the caller, not a runtime retry
        throw new IllegalStateException("Backend type was not provided by configuration source", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling HybridClientFactory.getOrCreate(null, config) or HybridClientFactory.getOrCreate("", config). This typically originates from a missing --hybrid CLI argument value, a null returned by a configuration parser, or an unset environment variable that was expected to provide the backend name.

Common situations: CLI flag --hybrid is provided without a value (or with trailing space stripped); the backend name is read from a config file/JSON that has a null or missing 'hybrid' key; programmatic integration code passes a variable that was never assigned; the value comes from an environment variable that was not set in the deployment.

Related errors


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