docling-project/docling · error · ArtifactDownloadError

Artifact download redirect is missing a Location header.

Error message

Artifact download redirect is missing a Location header.

What it means

Raised as ArtifactDownloadError by _next_redirect_url when a response is classified as a redirect (3xx) but carries no Location header. The manual redirect follower cannot determine the next URL, so the download aborts.

Source

Thrown at docling/service_client/client.py:1959

                raise ArtifactDownloadError(
                    "Too many redirects while downloading artifact."
                )
        except httpx.HTTPError as exc:
            raise ArtifactDownloadError(f"Artifact download failed: {exc}") from exc

    def _validate_artifact_url(self, url: str) -> None:
        if self._allow_private_artifact_urls:
            return
        if not _is_safe_artifact_url(url):
            raise ArtifactDownloadError(
                f"Refusing to download artifact from a non-public URL: {url}."
            )

    @staticmethod
    def _next_redirect_url(current_url: str, response: httpx.Response) -> str:
        location = response.headers.get("location")
        if not location:
            raise ArtifactDownloadError(
                "Artifact download redirect is missing a Location header."
            )
        return str(httpx.URL(current_url).join(location))

    def _check_artifact_size(self, total: int) -> None:
        if total > self._max_artifact_download_bytes:
            raise ArtifactDownloadError(
                "Artifact exceeds max_artifact_download_bytes "
                f"({self._max_artifact_download_bytes} bytes)."
            )

    def _source_to_upload_files(
        self,
        source: Path | DocumentStream,
    ) -> dict[str, tuple[str, IO[bytes], str]]:
        """Build multipart files dict for a sync upload. Passes file handles — no full read."""
        if isinstance(source, Path):
            filename = source.name

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Reproduce with curl -i against the artifact URL and inspect the 3xx response headers
  2. Fix the proxy/gateway to forward or set the Location header
  3. Bypass the offending proxy layer for artifact traffic
Defensive patterns

Strategy: try-catch

Validate before calling

import requests
r = requests.get(artifact_url, allow_redirects=False)
if r.is_redirect:
    assert r.headers.get('location'), 'proxy strips Location header'

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 as exc:
    if 'missing a Location header' in str(exc):
        alert_ops('artifact proxy strips Location on redirects')

Prevention

When it happens

Trigger: Artifact server returns 301/302/307/308 with a missing or empty Location header — typically a misconfigured reverse proxy or a stripped header.

Common situations: Proxies that drop Location on redirect; object-store gateways with buggy redirect responses; security appliances rewriting responses.

Related errors


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