docling-project/docling · error · ArtifactDownloadError
Resource bundle contains an unsafe path: {member!r}
Error message
Resource bundle contains an unsafe path: {member!r} What it means
Raised as ArtifactDownloadError when extracting a downloaded resource bundle ZIP: one of its member paths (e.g. '../../etc/passwd') would resolve outside the extraction directory. This is a zip-slip containment guard applied even though bundles nominally come from the trusted docling-serve service. Per the exception docstring it is normally caught internally and surfaced as a FAILURE ConversionResult rather than propagated.
Source
Thrown at docling/service_client/client.py:1796
except zipfile.BadZipFile as exc:
raise ArtifactDownloadError(
f"Downloaded resource bundle is not a valid ZIP: {exc}"
) from exc
json_path = self._find_bundle_json(base_dir)
document = DoclingDocument.load_from_json(json_path)
# Embed while the extracted artifacts are still on disk, then let the
# temp dir be removed: the returned document is fully in-memory.
self._embed_referenced_images(document, base_dir)
return document
@staticmethod
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: PathView on GitHub (pinned to 61d76f1ff3)
Solutions
- Check the resulting ConversionResult.status/errors — the failure is attached to that document's result, and other documents in the batch still succeed
- Verify the docling-serve deployment version and that the artifact store is not tampering with bundle contents
- If images are not needed, request images='embedded' or omit image export so no bundle ZIP is downloaded
Example fix
// before
result = client.convert(Path('doc.pdf'), options=options_with_referenced_images)
// after (inspect per-document result instead of expecting an exception)
results = list(client.convert_all([Path('doc.pdf')], options=options))
for res in results:
if res.status == ConversionStatus.FAILURE:
print(res.errors) # ArtifactDownloadError details appear here Defensive patterns
Strategy: try-catch
Type guard
def is_artifact_download_error(exc: BaseException) -> bool:
return isinstance(exc, ArtifactDownloadError) Try / catch
try:
results = list(client.convert_all(sources))
except ArtifactDownloadError:
... # rare: only when the error escapes internal handling
# preferred: inspect per-document results
for res in results:
if res.status == ConversionStatus.FAILURE:
handle(res.errors) Prevention
- Treat ArtifactDownloadError on bundles as a per-document FAILURE result, not a global exception
- Only enable referenced-image bundles against a trusted, version-matched docling-serve
When it happens
Trigger: Calling convert()/convert_all() with images='referenced' (bundle mode) against a service that returns a ZIP whose member names contain absolute paths or '../' traversal segments that resolve beyond the temp extraction dir.
Common situations: A compromised or buggy docling-serve version writes member names with leading slashes or traversal; a proxy/CDN rewrites the artifact; a hand-crafted bundle is served from a misconfigured object store presigned URL.
Related errors
- Resource bundle references an image outside the bundle: {uri
- ZIP slip attempt: {info.filename}
- ZIP slip attempt: {member.filename}
- Too many redirects while downloading artifact.
- Refusing to download artifact from a non-public URL: {url}.
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/532f72937cd5fb05.
Report an issue: GitHub.