opendatalab/MinerU · error · RuntimeError

Failed to load file {upload.original_name}: {exc}

Error message

Failed to load file {upload.original_name}: {exc}

What it means

RuntimeError raised by load_parse_inputs in fast_api.py when read_fn(Path(upload.path)) throws while loading an already-stored upload from disk, just before parsing starts (run in a worker thread via asyncio.to_thread). The original exception is chained (__cause__). It means the file passed upload-time validation but could not be read afterwards: deleted by the retention/cleanup sweeper, moved, permission problems, or a full/corrupted disk.

Source

Thrown at mineru/cli/fast_api.py:816

            StoredUpload(
                original_name=upload.original_name,
                stem=effective_stem,
                path=upload.path,
            )
            for upload, effective_stem in zip(uploads, normalized_stems)
        ]
    return uploads


def load_parse_inputs(uploads: list[StoredUpload]) -> tuple[list[str], list[bytes]]:
    pdf_file_names = []
    pdf_bytes_list = []

    for upload in uploads:
        try:
            pdf_bytes = read_fn(Path(upload.path))
        except Exception as exc:
            raise RuntimeError(f"Failed to load file {upload.original_name}: {exc}") from exc
        pdf_file_names.append(upload.stem)
        pdf_bytes_list.append(pdf_bytes)
    return pdf_file_names, pdf_bytes_list


async def run_parse_job(
    output_dir: str,
    uploads: list[StoredUpload],
    request_options: ParseRequestOptions | AsyncParseTask,
    config: dict[str, Any],
) -> list[str]:
    pdf_file_names, pdf_bytes_list = await asyncio.to_thread(load_parse_inputs, uploads)
    actual_lang_list = normalize_lang_list(request_options.lang_list, len(pdf_file_names))
    response_file_names = list(pdf_file_names)

    parse_kwargs = dict(
        output_dir=output_dir,
        pdf_file_names=list(pdf_file_names),

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Look at the chained __cause__ in the traceback — it names the real IOError reason (missing file vs permission vs I/O error).
  2. Check that the upload directory is writable and persistent for the API process for the whole task lifetime; move it off tmpfs if containers restart.
  3. Make task/file retention (MINERU_API_TASK_RETENTION_SECONDS and related cleanup intervals) longer than your worst-case queue wait so files are not swept early.
  4. Retry the request: if it was a transient cleanup race or disk blip, a fresh upload succeeds.

Example fix

# before
task = requests.post(f'{base}/file_parse', files=files).json()
# ...later, task fails with 'Failed to load file report.pdf: [Errno 2] No such file or directory'

# after (client-side guard)
resp = requests.post(f'{base}/file_parse', files=files)
if resp.status_code >= 500:
    resp = requests.post(f'{base}/file_parse', files=files)  # retry once on load failure
Defensive patterns

Strategy: retry

Try / catch

resp = submit(files)
if task_failed_with(resp, 'Failed to load file'):
    resp = submit(files)  # one retry: transient cleanup race / disk blip

Prevention

When it happens

Trigger: The task sat in the queue long enough that the background cleanup deleted the upload before a worker read it; two requests racing where one cleanup removes the temp file; the upload directory is on ephemeral storage (container restart, tmpfs clear); OS-level permission change on the uploads dir between upload and parse.

Common situations: Long queues under load with aggressive task retention settings; deployments where the API's upload dir is not persistent; security software quarantining files; disk-full events truncating written files.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/1c975f2abd807790. Report an issue: GitHub.