PaddlePaddle/PaddleOCR · error · JobFailedError
Job failed
Error message
Job {job_id} failed: {error_msg} What it means
Raised as JobFailedError by the async poller when a submitted job's state transitions to 'failed' on the service side. The message embeds the job_id and the service-provided errorMsg (or 'Unknown error' when the payload omits it). This means the request was accepted but processing failed downstream, so retrying with identical inputs often fails again.
Solutions
- Read the errorMsg embedded in the exception to identify the service-side reason before changing anything.
- Verify the input file: open the file_url/file_path locally, confirm it is a supported format and not truncated.
- Check that the model and options match the input (e.g. document-parsing model for PDFs, OCR model for images).
- Retry once with a fresh job after fixing the input; if errorMsg indicates a transient internal error, recreate the job with the same input.
- If failures persist, capture job_id and errorMsg and report to PaddleOCR AI Studio support.
Example fix
// before
result = await client.ocr(file_path="doc.pdf") # raises JobFailedError
// after
try:
result = await client.ocr(file_path="doc.pdf")
except JobFailedError as e:
print(f"job {e.job_id} failed: {e.message}")
# inspect input file / model choice, then resubmit Defensive patterns
Strategy: try-catch
Try / catch
from paddleocr._api_client.errors import JobFailedError
try:
result = await client.ocr(file_path=path)
except JobFailedError as e:
# e.job_id and str(e) carry the service-side reason
log.warning("job %s failed: %s", e.job_id, e)
raise Prevention
- Validate the file opens and is a supported format before submitting.
- Match the model to the input type (OCR for images, document parsing for PDFs).
- Log errorMsg from every JobFailedError to catch recurring input problems.
When it happens
Trigger: Calling an async API method that polls to completion (e.g. create OCR/document-parsing job then wait) where get_job_status() eventually returns state == 'failed'. The payload's errorMsg field supplies the reason; if absent, 'Unknown error' is used.
Common situations: Corrupt or unreadable input file at the given file_url, unsupported file format or oversized document, model mismatch for the input type, or transient service-side failures during extraction. Also seen when the uploaded URL expires before the service fetches it.
Related errors
- Destination already exists
- Job failed
- Model is not a document parsing model.
- resourceUrl is required.
- Timed out after ms waiting for job
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/dd89a7be8eada5ff.
Report an issue: GitHub.
Appendix: source
Thrown at paddleocr/_api_client/_async_poller.py:72
start = loop.time()
deadline = start + self._max_wait_time
while True:
now = loop.time()
if now >= deadline:
raise PollTimeoutError(job_id, now - start)
data = await self._http.get_job_status(job_id)
state = validate_state(data)
if state == "done":
json_url = validate_result_json_url(data)
jsonl_data = await self._http.fetch_jsonl(json_url)
return jsonl_data, data
if state == "failed":
error_msg = data.get("errorMsg", "Unknown error")
raise JobFailedError(job_id, error_msg)
remaining = deadline - loop.time()
if remaining <= 0:
raise PollTimeoutError(job_id, loop.time() - start)
await asyncio.sleep(min(interval, remaining))
interval = min(interval * self._multiplier, self._max_interval)
async def get_status(self, job_id: str) -> JobStatus:
data = await self._http.get_job_status(job_id)
return job_status_from_data(job_id, data)
async def get_batch_status(self, batch_id: str) -> BatchStatus:
data = await self._http.get_batch_status(batch_id)
return parse_batch_status(batch_id, data)
View on GitHub (pinned to 2661c7c0ef)