docling-project/docling · error · ServiceUnavailableError
Service request failed after retry loop.
Error message
Service request failed after retry loop.
What it means
This is the terminal fallback of the async client's retry loop: the request was attempted max_retries+1 times, every attempt either failed transport-level with delays exhausted or returned a retryable HTTP status, and the loop exited without a usable response. ServiceUnavailableError is raised to signal the service did not yield a successful response within the retry budget. Unlike error 350, the last attempt may have been an HTTP-level retry (429/5xx) rather than a transport exception.
Source
Thrown at docling/service_client/_async_client.py:709
method=method_name,
exc=exc,
attempt=attempt,
max_retries=max_retries,
)
if delay is not None:
await asyncio.sleep(delay)
continue
raise ServiceUnavailableError(
"Service transport request failed.",
detail=str(exc),
) from exc
result, delay = self._check_retry(response, attempt, max_retries)
if result is not None:
return result
if delay > 0:
await asyncio.sleep(delay)
raise ServiceUnavailableError("Service request failed after retry loop.")
async def _submit_convert_task(
self,
source: SourceType,
options: ConvertDocumentsRequestOptions,
target: SubmitTarget,
async_client: httpx.AsyncClient,
request_headers: dict[str, str] | None = None,
) -> TaskStatusResponse:
source = self._normalize_source(source)
source_name = self._source_name(source)
logger.info("Submitting convert task for source=%s", source_name)
if isinstance(source, HttpSourceRequest):
request = ConvertDocumentsRequest(
options=options,
sources=[source],
target=target,
)View on GitHub (pinned to 61d76f1ff3)
Solutions
- Increase http_retries and/or connect/read timeouts on the client so the retry window covers transient outages.
- Reduce request concurrency to lower pressure on the service.
- Check service health/logs and wait for it to recover before resubmitting.
- Implement application-level backoff and resubmit the failed request later.
Example fix
# before
client = DocumentConverterClient(base_url=url) # default retries
result = await client.convert_file(f) # ServiceUnavailableError after retry loop
# after
client = DocumentConverterClient(base_url=url, http_retries=8, http_read_timeout=120.0)
async with client:
try:
result = await client.convert_file(f)
except ServiceUnavailableError:
await asyncio.sleep(60)
result = await client.convert_file(f) Defensive patterns
Strategy: retry
Try / catch
from docling.service_client.exceptions import ServiceUnavailableError
try:
result = await client.convert_file(f)
except ServiceUnavailableError:
await asyncio.sleep(backoff)
result = await client.convert_file(f) # resubmit after service recovers Prevention
- Size http_retries to cover expected service restarts/overload windows.
- Throttle client concurrency to avoid pushing the service into sustained 5xx.
- Watch service health and pause submission during outages.
When it happens
Trigger: Service persistently returning 503/429/502 across all attempts with Retry-After or backoff delays; sustained overload or the service being down for maintenance; retry budget (http_retries) too small for the outage duration.
Common situations: Hammering a small docling-serve instance with a large batch until it sheds load; service restarting/deploying mid-job; autoscaling cold start taking longer than the client retry window.
Related errors
- Service transport request failed.
- {error_message}
- Service returned HTTP {response.status_code} after retries.
- Service transport request failed after retries.
- Service transport request failed.
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/fc5dc0734e953261.
Report an issue: GitHub.