opendataloader-project/opendataloader-pdf · error · IOException

Backend processing failed for %d page(s) with fallback disab

Error message

Backend processing failed for %d page(s) with fallback disabled: pages %s

What it means

IOException thrown by failFastIfBackendFailedWithoutFallback when the backend returned partial_success — it processed some pages but populated backendFailedPages with the ones it could not handle — and hybridConfig.isFallbackToJava() is false. The message lists the count and the 1-indexed failed page numbers. This is distinct from error 84 (whole-backend crash): here the backend responded but failed on specific pages.

Source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/processors/HybridDocumentProcessor.java:493

     * making backend failures invisible to automation.
     *
     * @param backendFailedPages 0-indexed pages that the backend failed to process.
     * @param hybridConfig       Hybrid configuration; consulted for the fallback flag.
     * @throws IOException if {@code backendFailedPages} is non-empty and
     *                     {@code hybridConfig.isFallbackToJava()} returns false. The
     *                     exception message lists the 1-indexed failed page numbers.
     */
    static void failFastIfBackendFailedWithoutFallback(
            Set<Integer> backendFailedPages,
            HybridConfig hybridConfig) throws IOException {
        Objects.requireNonNull(backendFailedPages, "backendFailedPages");
        Objects.requireNonNull(hybridConfig, "hybridConfig");
        if (backendFailedPages.isEmpty() || hybridConfig.isFallbackToJava()) {
            return;
        }
        List<Integer> failedPages1Indexed = backendFailedPages.stream()
            .map(p -> p + 1).sorted().collect(Collectors.toList());
        throw new IOException(String.format(
            "Backend processing failed for %d page(s) with fallback disabled: pages %s",
            backendFailedPages.size(), failedPages1Indexed));
    }

    /**
     * Filters all pages using ContentFilterProcessor.
     */
    private static Map<Integer, List<IObject>> filterAllPages(
            String inputPdfName,
            Config config,
            Set<Integer> pagesToProcess,
            int totalPages) throws IOException {

        Map<Integer, List<IObject>> filteredContents = new HashMap<>();

        for (int pageNumber = 0; pageNumber < totalPages; pageNumber++) {
            if (!shouldProcessPage(pageNumber, pagesToProcess)) {
                filteredContents.put(pageNumber, new ArrayList<>());

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Enable fallback so failed pages are reprocessed through the Java path: set hybridConfig.setFallbackToJava(true) / --hybrid-fallback.
  2. Inspect the listed pages (1-indexed in the message): open those pages in the source PDF and check for corruption, excessive size, or unsupported features, then re-run after fixing the source.
  3. If strict no-fallback is policy, fix or upgrade the backend so it handles those pages, then retry.
  4. Increase backend timeout (hybrid_timeout) if the failures look like per-page timeouts on heavy pages.

Example fix

# before: backend partial success, no fallback -> fail
$ odl-pdf doc.pdf --hybrid docling-fast --hybrid-url http://b:8080 --hybrid-fallback off
-> Backend processing failed for 2 page(s) with fallback disabled: pages [7, 12]
# after: let failed pages fall back to Java
$ odl-pdf doc.pdf --hybrid docling-fast --hybrid-url http://b:8080 --hybrid-fallback on
Defensive patterns

Strategy: fallback

Validate before calling

// Inspect the message's page list and decide before failing:
// If per-page fallback is acceptable, set isFallbackToJava(true) before processing.
boolean strict = !config.getHybridConfig().isFallbackToJava();
if (strict) log.warn("Backend partial failures will hard-stop the run (fallback disabled)");

Type guard

static boolean isPartialBackendFailureNoFallback(IOException e) {
    return e.getMessage() != null
        && e.getMessage().startsWith("Backend processing failed for ")
        && e.getMessage().contains("with fallback disabled");
}

Try / catch

try {
    HybridDocumentProcessor.process(inputPdfName, config);
} catch (IOException e) {
    var m = e.getMessage();
    if (m != null && m.startsWith("Backend processing failed for ") && m.contains("with fallback disabled")) {
        // e.g. "... 2 page(s) ... pages [7, 12]" — inspect those pages or enable fallback
        config.getHybridConfig().setFallbackToJava(true);
        HybridDocumentProcessor.process(inputPdfName, config);
    } else throw e;
}

Prevention

When it happens

Trigger: processBackendPath returns with a non-empty backendFailedPages set (backend reported partial_success), hybridConfig.isFallbackToJava() is false, so failFastIfBackendFailedWithoutFallback throws rather than silently leaving gaps in the output.

Common situations: Backend times out or errors on a few complex/corrupt pages while succeeding on the rest, and the operator runs with --hybrid-fallback off for strict semantics. A backend version that cannot handle a particular page feature (e.g. a huge image) returns partial_success.

Related errors


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