docling-project/docling · error · ServiceUnavailableError

{error_message}

Error message

{error_message}

What it means

In the sync client's retry handling, _retry_with_exponential_backoff is called for retryable HTTP statuses without a Retry-After header. When attempt >= max_retries it gives up and raises ServiceUnavailableError with the caller-provided error_message (which names the failing operation) plus status code and response detail. It marks definitive exhaustion of the exponential backoff budget.

Solutions

  1. Check the service logs for the underlying 5xx cause (often one problematic document).
  2. Increase http_retries so transient 5xx bursts are absorbed.
  3. Isolate and retry the failing request separately; skip the poison document in batch runs.
  4. If errors are deterministic, the document or options may trigger a server bug — report upstream with the detail payload.

Example fix

# before
client = DocumentConverterClient(url)  # default retries
for f in files:
    client.convert_file(f)  # ServiceUnavailableError on server 500s

# after
client = DocumentConverterClient(url, http_retries=5)
for f in files:
    try:
        client.convert_file(f)
    except ServiceUnavailableError as e:
        log.error('skipping %s: %s', f, e)
Defensive patterns

Strategy: retry

Try / catch

from docling.service_client.exceptions import ServiceUnavailableError

for f in files:
    try:
        results.append(client.convert_file(f))
    except ServiceUnavailableError as e:
        log.error('failed %s status=%s detail=%s', f, e.status_code, e.detail)
        failed.append(f)  # retry later, don't abort the batch

Prevention

When it happens

Trigger: Service returning 5xx (e.g. 500/503) on every attempt for operations like file upload or task submission until retries run out; sustained server errors during batch processing; max_retries set low combined with a briefly failing endpoint.

Common situations: docling-serve throwing internal errors on a specific corrupt document; service under heavy load returning 503 for all requests; API rate limiting implemented as plain 503 without Retry-After.

Related errors


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

Appendix: source

Thrown at docling/service_client/client.py:594

            )
        if response.status_code in {429, 503}:
            return self._retry_with_retry_after_header(
                response=response,
                attempt=attempt,
                max_retries=max_retries,
            )
        return response, 0.0

    def _retry_with_exponential_backoff(
        self,
        response: httpx.Response,
        attempt: int,
        max_retries: int,
        error_message: str,
    ) -> tuple[httpx.Response | None, float]:
        if attempt < max_retries:
            return None, self._exponential_backoff_delay(attempt)
        raise ServiceUnavailableError(
            error_message,
            status_code=response.status_code,
            detail=self._http_error_detail(response),
        )

    def _retry_with_retry_after_header(
        self,
        response: httpx.Response,
        attempt: int,
        max_retries: int,
    ) -> tuple[httpx.Response | None, float]:
        retry_after_delay = self._retry_after_delay_seconds(response)
        if retry_after_delay is None:
            return response, 0.0
        if attempt < max_retries:
            return None, retry_after_delay
        raise ServiceUnavailableError(
            f"Service returned HTTP {response.status_code} after retries.",

View on GitHub (pinned to 61d76f1ff3)