opendataloader-project/opendataloader-pdf · error · IOException

Invalid response: missing 'document' field

Error message

Invalid response: missing 'document' field

What it means

The response parsed as JSON and did not report status:'failure', but the required 'document' field is absent. parseResponse needs root.get("document") to extract json_content and per-page content, so its absence means the server returned an unexpected schema. This guards against silently producing an empty HybridResponse from a malformed reply.

Source

Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/DoclingFastServerClient.java:223

        JsonNode statusNode = root.get("status");
        String status = statusNode != null ? statusNode.asText() : "";
        if ("failure".equals(status)) {
            JsonNode errorsNode = root.get("errors");
            String errorMessage = errorsNode != null ? errorsNode.toString() : "Unknown error";
            throw new IOException("Docling Fast Server processing failed: " + errorMessage);
        }

        // Log partial_success status
        if ("partial_success".equals(status)) {
            JsonNode errorsNode = root.get("errors");
            LOGGER.log(Level.WARNING, "Backend returned partial_success: {0}",
                errorsNode != null ? errorsNode.toString() : "no error details");
        }

        // Extract document content
        JsonNode documentNode = root.get("document");
        if (documentNode == null) {
            throw new IOException("Invalid response: missing 'document' field");
        }

        JsonNode jsonContent = documentNode.get("json_content");

        // Extract per-page content from json_content if available
        Map<Integer, JsonNode> pageContents = extractPageContents(jsonContent);

        // Extract failed pages (1-indexed) from partial_success responses
        List<Integer> failedPages = extractFailedPages(root);

        // Extract per-step pipeline timings (layout, ocr, table_structure, etc.)
        JsonNode timingsNode = root.get("timings");

        return new HybridResponse(null, null, jsonContent, pageContents, failedPages, timingsNode);
    }

    /**
     * Extracts per-page content from the DoclingDocument JSON structure.

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Confirm the docling-fast-server version matches the client's expected response schema
  2. Log the raw response body to inspect the actual envelope
  3. Upgrade or downgrade client/server to a compatible pair
  4. Hit the server directly (bypass proxies) to rule out body rewriting
Defensive patterns

Strategy: validation

Validate before calling

// Not generally possible client-side without the raw body; if you mirror
// responses in a test double, assert the schema of your mock server:
assert responseJson.has("document") : "server must return a 'document' field";

Try / catch

try {
    return client.convert(request);
} catch (IOException e) {
    if (e.getMessage().contains("missing 'document' field")) {
        log.error("schema mismatch with docling-fast-server version — align versions");
    }
    throw e;
}

Prevention

When it happens

Trigger: objectMapper.readTree(body) succeeds and status != 'failure', but root.get("document") returns null.

Common situations: Version skew: client expects the docling-serve-compatible envelope but the server returns a different shape; server returns an error wrapped in a non-standard JSON object with status omitted; proxy injecting an unrelated JSON body.

Related errors


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