NVIDIA / NVIDIA/NeMo-Retriever
[BUG]: Deadlock (infinite loop) when paddle is not ready
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 3k
- Forks
- 349
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 116
Description
Version
25.09 (25.9.0)
Which installation method(s) does this occur on?
No response
Describe the bug.
Jobs hang indefinitely when Paddle is unready; client defaults to infinite retries; submit_job not gated by readiness
- Impact: Ingestion sessions can run for 30+ minutes with near‑zero utilization when Paddle OCR is unready; no fail‑fast or clear error. Users see 0% progress for small batches.
- Versions:
- nv-ingest-client: 25.9.0
- nv-ingest-api: 25.9.0
- Environment: NV‑Ingest API exposed via gateway (
http://<gw-host>:80). Client usesIngestor(...).extract(...).split(...).embed().ingest(show_progress=True)with defaults.
Steps to reproduce
- Run NV‑Ingest API without a working Paddle endpoint (e.g., unset
PADDLE_HTTP_ENDPOINTor set to an unreachable URL inside the cluster). - Confirm health shows Paddle unready:
curl -s http://<gw-host>:80/v1/health/ready # returns 503 with JSON including: "paddle_ready": false - From a client, submit a small batch (e.g., 6 PDFs) using
nv-ingest-clientdefaults (no explicitmax_job_retries). - Observe the client logs: “Starting batch processing for 6 jobs…” and then no progress; process continues indefinitely with low CPU/GPU.
Observed behavior
- Health reports Paddle unready (503) but
submit_jobaccepts requests. Jobs never become ready. Client polls forever by default. - Example client log:
Starting batch processing for 6 jobs with batch size 32. ... 5 minutes elapse ... ⏰ TIMEOUT WARNING: NV-Ingest processing of 6 file(s) has been running for 300.0s (timeout: 300s) - Health sample:
HTTP/1.1 503 {"ingest_ready":true,"pipeline_ready":true,"paddle_ready":false,"yolox_graphic_elements_ready":true,"yolox_page_elements_ready":true,"yolox_table_structure_ready":true}
Expected behavior
- Either:
- API rejects
submit_jobfor tasks that require Paddle (or other unready components) with 503 and a clear message, or - Client fails fast with a clear error when
/v1/health/readyreports unready dependencies, or - Client times out after a finite number of retries by default, returning an actionable error.
- API rejects
Analysis (suspected root cause)
- Health endpoint exposes Paddle readiness:
READY_CHECK_ENV_VAR_MAP = {
"paddle": "PADDLE_HTTP_ENDPOINT",
"yolox_graphic_elements": "YOLOX_GRAPHIC_ELEMENTS_HTTP_ENDPOINT",
"yolox_page_elements": "YOLOX_HTTP_ENDPOINT",
"yolox_table_structure": "YOLOX_TABLE_STRUCTURE_HTTP_ENDPOINT",
}
- Paddle endpoint defaults (when present) are read from env:
paddle_http_endpoint: str = os.getenv("PADDLE_HTTP_ENDPOINT", "https://ai.api.nvidia.com/v1/cv/baidu/paddleocr")
paddle_infer_protocol: str = os.getenv("PADDLE_INFER_PROTOCOL", "http")
- The client’s
Ingestor.ingestdefaults to infinite retries:
DEFAULT_TIMEOUT: int = 100
DEFAULT_MAX_RETRIES: int = None
DEFAULT_VERBOSE: bool = False
timeout: int = kwargs.pop("timeout", DEFAULT_TIMEOUT)
max_job_retries: int = kwargs.pop("max_job_retries", DEFAULT_MAX_RETRIES)
verbose: bool = kwargs.pop("verbose", DEFAULT_VERBOSE)
- Retry loop requeues jobs on 202 (not ready) when
max_job_retriesis None:
except TimeoutError:
self.retry_counts[job_index] += 1
if self.max_job_retries is None or self.retry_counts[job_index] <= self.max_job_retries:
# not ready → keep retrying indefinitely when None
self.retry_job_ids.append(job_index)
else:
...
- Batch cycle continues while there are retries:
logger.info(f"Starting batch processing for {total_jobs} jobs with batch size {self.batch_size}.")
while (submitted_new_indices_count < total_jobs) or self.retry_job_ids:
Proposed fixes
- Server-side:
- Gate
/v1/submit_job: if a submission’s task chain requires Paddle/YOLOX/etc. and the corresponding readiness is false, return 503 with explicit dependency details (e.g., “paddle not ready; check PADDLE_HTTP_ENDPOINT/egress/auth”). - Optionally transition such jobs to FAILED immediately with a clear reason instead of accepting and then returning 202 indefinitely from fetch.
- Gate
- Client-side (nv-ingest-client):
- Change default
max_job_retriesfromNoneto a finite number (e.g., 60) to prevent infinite loops by default. - Before submission, optionally call
/v1/health/readyand fail fast with a user-friendly error if required components are unready (behind a flag that can be enabled by default). - When fetch returns 202 for longer than N minutes, surface a clear error citing
/v1/health/readystate to guide remediation.
- Change default
Workarounds for users (until fixed)
- Disable Paddle-dependent tasks (e.g., image/infographic extraction, NV‑Ingest captions) or explicitly set a finite
max_job_retries. - Ensure
PADDLE_HTTP_ENDPOINTand credentials are configured and reachable from within the cluster.
Acceptance criteria
- Submissions that require an unready dependency are rejected with 503 and a clear message, or client fails fast with an actionable error.
- Default client behavior does not loop indefinitely when dependencies are down.
- Documentation clarifies required env vars and readiness gating behavior.
I can file this for you or tailor the wording for your issue tracker template if you share it.
- Drafted an actionable nv‑ingest issue describing the hang, clear repro, and proposed fixes (server gating and client defaults).
- Highlighted code points where infinite retries and readiness checks are defined, and included health evidence showing Paddle unready.
Minimum reproducible example
Relevant log output
Other/Misc.
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the readiness map in upstream/nv-ingest/src/nv_ingest/api/v1/health.py, then trace submit_job handling and the retry loop in client/src/nv_ingest_client/client/client.py and client/src/nv_ingest_client/client/interface.py. Compare the health response with submission and polling behavior; done means unready dependencies produce a clear finite failure instead of indefinite retries, with the documented acceptance criteria satisfied.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100