NVIDIA / NVIDIA/NeMo-Retriever

[BUG]: Deadlock (infinite loop) when paddle is not ready

Open
#1,052 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
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 uses Ingestor(...).extract(...).split(...).embed().ingest(show_progress=True) with defaults.
Steps to reproduce
  1. Run NV‑Ingest API without a working Paddle endpoint (e.g., unset PADDLE_HTTP_ENDPOINT or set to an unreachable URL inside the cluster).
  2. Confirm health shows Paddle unready:
    curl -s http://<gw-host>:80/v1/health/ready
    # returns 503 with JSON including: "paddle_ready": false
    
  3. From a client, submit a small batch (e.g., 6 PDFs) using nv-ingest-client defaults (no explicit max_job_retries).
  4. 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_job accepts 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_job for 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/ready reports unready dependencies, or
    • Client times out after a finite number of retries by default, returning an actionable error.
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.ingest defaults 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_retries is 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.
  • Client-side (nv-ingest-client):
    • Change default max_job_retries from None to a finite number (e.g., 60) to prevent infinite loops by default.
    • Before submission, optionally call /v1/health/ready and 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/ready state to guide remediation.
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_ENDPOINT and 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.