PaddlePaddle/PaddleOCR · warning · ServiceUnavailableError

Service unavailable: {msg}

Error message

Service unavailable: {msg}

What it means

Raised as ServiceUnavailableError by raise_for_status() when the HTTP response status is 503 or 504. The exception carries the status code plus the message. It indicates a server-side or gateway problem (overload, maintenance, upstream timeout), typically transient and worth retrying with backoff.

Source

Thrown at paddleocr/_api_client/_core.py:158

        job_id=job_id,
        state=state,
        progress=progress,
        result=data.get("resultUrl"),
        error_msg=data.get("errorMsg"),
    )


def raise_for_status(status_code: int, msg: str) -> None:
    if 200 <= status_code < 300:
        return
    if status_code in (401, 403):
        raise AuthError(f"Authentication failed: {msg}")
    if status_code == 400:
        raise InvalidRequestError(f"Bad request: {msg}")
    if status_code == 429:
        raise RateLimitError(f"Rate limit exceeded: {msg}")
    if status_code in (503, 504):
        raise ServiceUnavailableError(status_code, f"Service unavailable: {msg}")
    raise APIError(status_code, msg)


def unwrap_api_response(payload: dict, status_code: int) -> dict:
    if not isinstance(payload, dict):
        raise ResponseFormatError("Response body must be a JSON object.")
    code = payload.get("code", 0)
    if code not in (0, None):
        raise APIError(status_code, extract_api_message_from_payload(payload) or "")
    data = payload.get("data")
    if not isinstance(data, dict):
        raise ResponseFormatError("Response JSON must contain object field 'data'.")
    return data


def extract_job_id(data: dict) -> str:
    job_id = data.get("jobId")
    if not isinstance(job_id, str) or not job_id:

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Retry the same request after a short backoff (seconds, then exponential), ideally 3-5 attempts.
  2. Check the service status page for ongoing incidents.
  3. Reduce request size (smaller files) if 504s correlate with large uploads.
  4. If persistent, report with timestamps to the service operator.

Example fix

# before
result = await client.ocr(file_path="big.pdf")

# after
import asyncio
for attempt in range(5):
    try:
        result = await client.ocr(file_path="big.pdf")
        break
    except ServiceUnavailableError:
        await asyncio.sleep(2 ** attempt)
Defensive patterns

Strategy: retry

Try / catch

from paddleocr._api_client.errors import ServiceUnavailableError
import asyncio

async def with_backoff(fn, *a, attempts=5, **kw):
    for i in range(attempts):
        try:
            return await fn(*a, **kw)
        except ServiceUnavailableError:
            if i == attempts - 1:
                raise
            await asyncio.sleep(2 ** i)

Prevention

When it happens

Trigger: Any API call during service maintenance or overload returning 503, or a long-running upstream operation timing out at the gateway returning 504.

Common situations: Service deployments/maintenance windows, traffic spikes, or intermittent gateway timeouts on large file uploads.

Understand the failure class

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/117cb529b99eda13. Report an issue: GitHub.