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
- Look at the chained __cause__ in the traceback — it names the real IOError reason (missing file vs permission vs I/O error).
- 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.
- 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.
- 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
- Keep upload directories on persistent, writable storage owned by the API user.
- Make retention/cleanup windows strictly longer than maximum queue wait times.
- Monitor disk space and upload-dir inode usage where the API writes.
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
- Task wait handle is unavailable
- Unsupported file type: {file_suffix}
- Task manager is shutting down
- Task manager is not initialized
- Unknown process_mode: {process_mode}
AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14).
Data as JSON: /api/errors/1c975f2abd807790.
Report an issue: GitHub.