infiniflow/ragflow · error · UnexpectedValidationError

Azure Blob: failed to download {name}: {exc}

Error message

Azure Blob: failed to download {name}: {exc}

What it means

Raised inside _iter_documents when downloading an individual blob fails and the failure is not a 'blob vanished' condition (those are logged and skipped). The download (get_blob_client + download_blob().readall()) error is wrapped in UnexpectedValidationError, aborting the whole batch iteration — including blobs already listed but not yet fetched.

Source

Thrown at common/data_source/azure_blob_connector.py:329

                # Download blob content. A blob that was deleted between the
                # listing and this fetch is genuinely gone — skip it. Any
                # other failure (throttling, transient 5xx, network) must
                # abort the run: the sync framework advances its watermark
                # from successfully yielded docs, so silently skipping a
                # transiently-failed blob while newer blobs succeed would
                # move the watermark past it and drop it permanently.
                try:
                    blob_client = self._container_client.get_blob_client(name)
                    data = blob_client.download_blob().readall()
                except Exception as exc:
                    if _is_blob_gone(exc):
                        logger.warning(
                            "Azure Blob: %s vanished between listing and fetch; skipping",
                            name,
                        )
                        continue
                    raise UnexpectedValidationError(f"Azure Blob: failed to download {name}: {exc}") from exc

                doc_updated_at = last_modified.astimezone(timezone.utc) if last_modified else datetime.now(timezone.utc)

                ext = _extension(name)
                doc = Document(
                    id=name,
                    source="azure_blob",
                    semantic_identifier=name,
                    extension=ext,
                    blob=data,
                    doc_updated_at=doc_updated_at,
                    size_bytes=len(data),
                    fingerprint=current_etag or None,
                    metadata={
                        "container": _container_name(self._container_client),
                        "etag": current_etag,
                        "prefix": self.prefix,
                    },

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Retry the ingestion run — the checkpoint logic deliberately avoids advancing the watermark past failed blobs (see the comment above the try), so nothing is lost
  2. If one specific blob always fails, download it manually (az storage blob download) to isolate whether it is corrupt, leased, or over a size limit
  3. Add exponential backoff around the whole ingestion run for transient network causes
  4. Check exc.__cause__ for the SDK error code (e.g. 500/timeout vs 403) to pick retry vs fix
Defensive patterns

Strategy: retry

Validate before calling

# Pre-check the blobs most likely to fail (size) using listing metadata:
for props in container_client.list_blobs(name_starts_with=prefix):
    if props.size > MAX_BLOB_BYTES:
        logger.warning("skipping oversized blob %s (%d bytes)", props.name, props.size)

Try / catch

try:
    for batch in connector.load_from_checkpoint(start, end, checkpoint):
        process(batch)
except UnexpectedValidationError as e:
    if "failed to download" not in str(e):
        raise
    # watermark was NOT advanced past the failed blob — safe to retry the run
    backoff_and_retry(whole_run, max_attempts=3)

Prevention

When it happens

Trigger: Listing succeeded, then download_blob().readall() throws for a specific blob: blob became unreadable (lease/permission change mid-run), a transient network reset during the read, or a payload too large for memory/time limits. _is_blob_gone(exc) returned False, so it is not treated as a vanished blob.

Common situations: Flaky networks on large blobs, concurrent deletes that leave the blob in a partially-gone state Azure still lists, or anti-virus/middleware terminating long streaming responses.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/deefd49c0fa48df1. Report an issue: GitHub.