docling-project/docling · error · ArtifactDownloadError

Resource bundle does not contain a top-level JSON document.

Error message

Resource bundle does not contain a top-level JSON document.

What it means

Raised as ArtifactDownloadError when, after extracting a resource bundle, no top-level *.json file can be found. The client expects the server to write the DoclingDocument JSON at the bundle root (with images under artifacts/); an empty or malformed bundle fails this check. Normally surfaced as a FAILURE ConversionResult, not thrown to callers.

Source

Thrown at docling/service_client/client.py:1808

    def _safe_extract_zip(bundle_zip: zipfile.ZipFile, base_dir: Path) -> None:
        # Guard against zip-slip even though bundles originate from our service.
        base_resolved = base_dir.resolve()
        for member in bundle_zip.namelist():
            target = (base_dir / member).resolve()
            if target != base_resolved and base_resolved not in target.parents:
                raise ArtifactDownloadError(
                    f"Resource bundle contains an unsafe path: {member!r}"
                )
        bundle_zip.extractall(base_dir)

    @staticmethod
    def _find_bundle_json(base_dir: Path) -> Path:
        # The server writes the document files at the bundle root and the
        # referenced images under artifacts/, so the document JSON is the
        # top-level *.json file.
        candidates = sorted(base_dir.glob("*.json"))
        if not candidates:
            raise ArtifactDownloadError(
                "Resource bundle does not contain a top-level JSON document."
            )
        return candidates[0]

    def _embed_referenced_images(
        self, document: DoclingDocument, base_dir: Path
    ) -> None:
        """Inline images referenced as relative files under ``base_dir``.

        This mirrors docling-core's ``DoclingDocument._with_embedded_pictures()``
        but is reimplemented here because that helper only embeds picture images
        and resolves relative ``Path`` URIs against the process working directory.
        Bundle artifacts are extracted into a temporary directory, so both
        picture and page image references must be resolved against ``base_dir``
        explicitly before being inlined.
        """

        base_resolved = base_dir.resolve()

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Check ConversionResult.errors for this document; retry the conversion once in case of a truncated artifact download
  2. Confirm client and docling-serve versions match (bundle layout is a shared contract)
  3. Inspect the bundle manually by fetching the presigned URL with curl to see whether a root-level JSON exists
Defensive patterns

Strategy: retry

Type guard

def is_artifact_download_error(exc: BaseException) -> bool:
    return isinstance(exc, ArtifactDownloadError)

Try / catch

if res.status == ConversionStatus.FAILURE:
    msgs = [e.error_message for e in res.errors]
    if any('top-level JSON' in m for m in msgs):
        retry_conversion(source)

Prevention

When it happens

Trigger: convert()/convert_all() with referenced-image bundle download where the ZIP contains only artifacts/ images, nested JSON files, or no JSON at all; sorted(glob('*.json')) at the extraction root returns nothing.

Common situations: Version mismatch between client and server bundle layout; server bug writing the document under a subdirectory; truncated/corrupted ZIP downloaded from an expiring presigned URL.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/8976c08933a3d8b7. Report an issue: GitHub.