opendataloader-project/opendataloader-pdf · error · IllegalArgumentException

Max concurrent requests must be positive: %s

Error message

Max concurrent requests must be positive: %s

What it means

HybridConfig.setMaxConcurrentRequests() rejects zero and negative values. The concurrency limit controls the Semaphore or thread pool size for parallel backend requests, and zero/negative concurrency is semantically invalid — it would mean no requests can ever execute. The default is DEFAULT_MAX_CONCURRENT_REQUESTS = 4.

Source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/HybridConfig.java:161

    /**
     * Gets the maximum number of concurrent requests to the backend.
     *
     * @return The maximum concurrent requests.
     */
    public int getMaxConcurrentRequests() {
        return maxConcurrentRequests;
    }

    /**
     * Sets the maximum number of concurrent requests to the backend.
     *
     * @param maxConcurrentRequests The maximum concurrent requests.
     * @throws IllegalArgumentException if the value is not positive.
     */
    public void setMaxConcurrentRequests(int maxConcurrentRequests) {
        if (maxConcurrentRequests <= 0) {
            throw new IllegalArgumentException("Max concurrent requests must be positive: " + maxConcurrentRequests);
        }
        this.maxConcurrentRequests = maxConcurrentRequests;
    }

    /**
     * Gets the default URL for a given hybrid backend.
     *
     * @param hybrid The hybrid backend name (docling, docling-fast, hancom, azure, google).
     * @return The default URL, or null if the backend requires explicit URL.
     */
    public static String getDefaultUrl(String hybrid) {
        if (hybrid == null) {
            return null;
        }
        String lowerHybrid = hybrid.toLowerCase();
        // Both "docling" and "docling-fast" (deprecated) use the same server
        if ("docling".equals(lowerHybrid) || "docling-fast".equals(lowerHybrid)) {
            return DOCLING_FAST_DEFAULT_URL;

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Set to at least 1 (sequential) or the default 4 for typical parallel processing.
  2. If computing dynamically, clamp: `setMaxConcurrentRequests(Math.max(1, computed))`.
  3. Use DEFAULT_MAX_CONCURRENT_REQUESTS constant if unsure.
  4. Check CLI/config for accidental zero values.

Example fix

// before: can produce 0 on single-core containers
config.setMaxConcurrentRequests(Runtime.getRuntime().availableProcessors() - 1);

// after: clamp to minimum 1
config.setMaxConcurrentRequests(
    Math.max(1, Runtime.getRuntime().availableProcessors() - 1));
Defensive patterns

Strategy: validation

Validate before calling

int concurrency = parseConcurrency(configSource);
if (concurrency <= 0) {
    throw new IllegalArgumentException(
        "Max concurrent requests must be >= 1. Got: " + concurrency);
}
config.setMaxConcurrentRequests(concurrency);

Type guard

public static boolean isValidConcurrency(int maxConcurrent) {
    return maxConcurrent > 0;
}

Try / catch

try {
    config.setMaxConcurrentRequests(requestedConcurrency);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("must be positive")) {
        // Use default instead of failing
        config.setMaxConcurrentRequests(HybridConfig.DEFAULT_MAX_CONCURRENT_REQUESTS);
        LOGGER.warning("Invalid concurrency, using default: "
            + HybridConfig.DEFAULT_MAX_CONCURRENT_REQUESTS);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling config.setMaxConcurrentRequests(0) or any negative integer. This typically comes from a CLI argument `--hybrid-concurrency 0`, a config file with a zero value, or a dynamic computation that produces zero (e.g., availableProcessors() - someOffset on a single-core machine).

Common situations: CLI argument `--hybrid-max-requests 0` (user intended to disable limits but 0 means disabled-concurrency); computing concurrency from Runtime.getRuntime().availableProcessors() and subtracting cores on a constrained container; config file typo setting the value to 0 instead of omitting it.

Related errors


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