elastic/elasticsearch · error · IllegalArgumentException

failure store document has unexpected structure, missing req

Error message

failure store document has unexpected structure, missing required [document.source] field

What it means

Thrown by RecoverFailureDocumentProcessor.execute when the incoming IngestDocument does not contain the nested 'document.source' field. This processor reconstructs the original document from a failure-store entry created by the pipeline's on-failure handling, so it expects a specific envelope structure with 'document', 'document.source', and 'error' keys.

Source

Thrown at modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/RecoverFailureDocumentProcessor.java:58

    public static final String MISSING_SOURCE_ERROR_MSG =
        "failure store document has unexpected structure, missing required [document.source] field";
    public static final String MISSING_ERROR_ERROR_MSG = "failure store document has unexpected structure, missing required [error] field";

    public static final String TYPE = "recover_failure_document";

    RecoverFailureDocumentProcessor(String tag, String description) {
        super(tag, description);
    }

    @Override
    @SuppressWarnings("unchecked")
    public IngestDocument execute(IngestDocument document) throws Exception {
        if (document.hasField(DOCUMENT_FIELD) == false) {
            throw new IllegalArgumentException(MISSING_DOCUMENT_ERROR_MSG);
        }

        if (document.hasField(SOURCE_FIELD_PATH) == false) {
            throw new IllegalArgumentException(MISSING_SOURCE_ERROR_MSG);
        }

        if (document.hasField(ERROR_FIELD) == false) {
            throw new IllegalArgumentException(MISSING_ERROR_ERROR_MSG);
        }

        // store pre-recovery data in ingest metadata
        storePreRecoveryData(document);

        // Get the nested 'document' field, which holds the original document and metadata.
        Map<String, Object> failedDocument = (Map<String, Object>) document.getFieldValue(DOCUMENT_FIELD, Map.class);

        // Copy the original index, routing, and id back to the document's metadata.
        String originalIndex = (String) failedDocument.get(INDEX_FIELD);
        if (originalIndex != null) {
            document.setFieldValue(IngestDocument.Metadata.INDEX.getFieldName(), originalIndex);
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify the document is a genuine failure-store entry containing the 'document' map with a nested 'source' key before invoking this processor.
  2. Ensure the pipeline is only used in the failure-store recovery path, not on raw documents.
  3. Inspect the document with a print/simulate pipeline step to confirm the 'document.source' field is present.

Example fix

// before: feeding a raw document to the recover_failure_document processor
// after: ensure the document is a failure-store entry
// doc must contain: { "document": { "source": {...} }, "error": {...} }
if (ingestDocument.hasField("document.source") == false) {
    throw new IllegalStateException("input is not a failure-store entry");
}
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking recover_failure_document, verify the envelope structure
if (document.hasField("document") == false
    || document.hasField("document.source") == false) {
    // skip recovery; the input is not a failure-store entry
    return;
}

Type guard

boolean isFailureStoreEntry(IngestDocument doc) {
    return doc.hasField("document")
        && doc.hasField("document.source")
        && doc.hasField("error");
}

Try / catch

try {
    // run pipeline with recover_failure_document
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("missing required [document.source]")) {
        // log and route to a dead-letter index; input is not a failure-store entry
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling the recover_failure_document processor on a document that lacks the 'document.source' field path. This happens when the input document was not produced by the failure store or was manually constructed without the full failure envelope.

Common situations: Misconfiguring a pipeline that chains into recover_failure_document without first routing through the failure store. Sending an ad-hoc document to a pipeline containing this processor. Schema drift between failure-store versions.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/a25d803323a0a679. Report an issue: GitHub.